home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / pgp20src.zip / CRYPTO.C < prev    next >
C/C++ Source or Header  |  1992-08-31  |  85KB  |  2,602 lines

  1. /*    crypto.c  - Cryptographic routines for PGP.
  2.     PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
  3.  
  4.     (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
  5.     The author assumes no liability for damages resulting from the use
  6.     of this software, even if the damage results from defects in this
  7.     software.  No warranty is expressed or implied.
  8.  
  9.     All the source code Philip Zimmermann wrote for PGP is available for
  10.     free under the "Copyleft" General Public License from the Free
  11.     Software Foundation.  A copy of that license agreement is included in
  12.     the source release package of PGP.  Code developed by others for PGP
  13.     is also freely available.  Other code that has been incorporated into
  14.     PGP from other sources was either originally published in the public
  15.     domain or was used with permission from the various authors.  See the
  16.     PGP User's Guide for more complete information about licensing,
  17.     patent restrictions on certain algorithms, trademarks, copyrights,
  18.     and export controls.  
  19. */
  20.  
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <time.h>
  25.  
  26. #include "mpilib.h"
  27. #include "mpiio.h"
  28. #include "random.h"
  29. #include "idea.h"
  30. #include "crypto.h"
  31. #include "keymgmt.h"
  32. #include "mdfile.h"
  33. #include "fileio.h"
  34. #include "language.h"
  35. #include "pgp.h"
  36.  
  37. #define ENCRYPT_IT FALSE    /* to pass to idea_file */
  38. #define DECRYPT_IT TRUE        /* to pass to idea_file */
  39.  
  40. /* The kbhit() function: Determines if a key has been hit.  May not be
  41.    available in some implementations */
  42.  
  43. int kbhit( void );
  44. int zipup(FILE *, FILE *);
  45. #ifdef  M_XENIX
  46. long time();
  47. #endif
  48.  
  49. /*--------------------------------------------------------------------------*/
  50.  
  51.  
  52. void CToPascal(char *s)
  53. {    /* "xyz\0" --> "\3xyz" ... converts C string to Pascal string */
  54.     int i,j;
  55.     j = string_length(s);
  56.     for (i=j; i!=0; i--)
  57.         s[i] = s[i-1];    /* move everything 1 byte to the right */
  58.     s[0] = j;        /* Pascal length byte at beginning */
  59. }    /* CToPascal */
  60.  
  61.  
  62. void PascalToC( char *s )
  63. {    /* "\3xyz" --> "xyz\0" ... converts Pascal string to C string */
  64.     int i,j;
  65.     for (i=0,j=((byte *) s)[0]; i<j; i++)
  66.         s[i] = s[i+1];    /* move everything 1 byte to the left */
  67.     s[i] = '\0';        /* append C string terminator */
  68. }    /* PascalToC */
  69.  
  70.  
  71. /* 
  72.     Note:  On MSDOS, the time() function calculates GMT as the local
  73.     system time plus a built-in timezone correction, which defaults to
  74.     adding 7 hours (PDT) in the summer, or 8 hours (PST) in the winter,
  75.     assuming the center of the universe is on the US west coast. Really--
  76.     I'm not making this up!  The only way to change this is by setting 
  77.     the MSDOS environmental variable TZ to reflect your local time zone,
  78.     for example "set TZ=MST7MDT".  This means add 7 hours during standard
  79.     time season, or 6 hours during daylight time season, and use MST and 
  80.     MDT for the two names of the time zone.  If you live in a place like 
  81.     Arizona with no daylight savings time, use "set TZ=MST7".  See the
  82.     Microsoft C function tzset().  Just in case your local software
  83.     environment is too weird to predict how to set environmental
  84.     variables for this, PGP also uses its own TZFIX variable in
  85.     config.pgp to optionally correct this problem further.  For example,
  86.     set TZFIX=-1 in config.pgp if you live in Colorado and the TZ
  87.     variable is undefined.
  88. */
  89.  
  90. word32 get_timestamp(byte *timestamp)
  91. /*    Return current timestamp as a byte array in internal byteorder,
  92.     and as a 32-bit word */
  93. {    word32 t;
  94.     t = time(NULL);    /* returns seconds since GMT 00:00 1 Jan 1970 */
  95.  
  96. #ifdef _MSC_VER
  97. #if (_MSC_VER == 700)
  98.     /*  Under MSDOS and MSC 7.0, time() returns elapsed time since
  99.      *  GMT 00:00 31 Dec 1899, instead of Unix's base date of 1 Jan 1970.
  100.      *  So we must subtract 70 years worth of seconds to fix this.
  101.      *  6/19/92  rgb 
  102.     */
  103. #define    LEAP_DAYS    (((unsigned long)70L/4)+1)
  104. #define CALENDAR_KLUDGE ((unsigned long)86400L * (((unsigned long)365L * 70L) + LEAP_DAYS))
  105.        t -= CALENDAR_KLUDGE;
  106. #endif
  107. #endif
  108.  
  109.     t += timeshift; /* timeshift derived from TZFIX in config.pgp */
  110.  
  111.     if (timestamp != NULL)
  112.     {    /* first, fill array in external byte order: */
  113.         put_word32(t, timestamp);
  114.         convert_byteorder(timestamp,4);    /* convert to internal byteorder */
  115.     }
  116.  
  117.     return(t);    /* return 32-bit timestamp integer */
  118. }    /* get_timestamp */
  119.  
  120.  
  121. int date_ymd(word32 *tstamp, int *year, int *month, int *day)
  122. /*    Given timestamp as seconds elapsed since 1970 Jan 1 00:00:00,
  123.     returns year (1970-2106), month (1-12), day (1-31).
  124.     Not valid for dates after 2100 Feb 28 (no leap day that year).
  125.     Also returns day of week (0-6) as functional return.
  126. */
  127. {    word32 days,y;
  128.     int m,d,i;
  129.     static short mdays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  130.     days = (*tstamp)/(unsigned long)86400L;    /* day 0 is 1970/1/1 */
  131.     days -= 730L;    /* align days relative to 1st leap year, 1972 */
  132.     y = ((days*4)/(unsigned long)1461L);    /* 1972 is year 0 */
  133.     /* reduce to days elapsed since 1/1 last leap year: */
  134.     d = (int) (days - ((y/4)*1461L));
  135.     *year = (int)(y+1972);
  136.     for (i=0; i<48; i++)    /* count months 0-47 */
  137.     {    m = i % 12;
  138.         d -= mdays[m] + (i==1);    /* i==1 is the only leap month */
  139.         if (d < 0)
  140.         {    d += mdays[m] + (i==1);
  141.             break;
  142.         }
  143.     }
  144.     *month = m+1;
  145.     *day = d+1;
  146.     i = (int)((days-2) % (unsigned long)7L);    /* compute day of week 0-6 */
  147.     return(i);    /* returns weekday 0-6; 0=Sunday, 6=Saturday */
  148. }    /* date_ymd */
  149.  
  150.  
  151. char *cdate(word32 *tstamp)
  152. /*    Return date string, given pointer to 32-bit timestamp */
  153. {    int month,day,year;
  154.     static char datebuf[20];
  155.     (void) date_ymd(tstamp,&year,&month,&day);
  156.     sprintf(datebuf,"%4d/%02d/%02d", year, month, day);
  157.     return (datebuf);
  158. }    /* cdate */
  159.  
  160.  
  161. char *ctdate(word32 *tstamp)
  162. /*    Return date and time string, given pointer to 32-bit timestamp */
  163. {    int hours,minutes;
  164.     static char tdatebuf[40];
  165.     long seconds;
  166.     seconds = (*tstamp) % (unsigned long)86400L;    /* seconds past midnight today */
  167.     minutes = (seconds+30L) / 60L;    /* round off to minutes past midnight */
  168.     hours = minutes / 60;            /* hours past midnight */
  169.     minutes = minutes % 60;            /* minutes past the hour */
  170.     sprintf(tdatebuf,"%s %02d:%02d GMT", cdate(tstamp), hours, minutes);
  171.     return (tdatebuf);
  172. }    /* ctdate */
  173.  
  174.  
  175.  
  176. /* Warn user he if key in keyfile at position fp of length pktlen, belonging
  177.  * to userid, is untrusted.  Return -1 if the user doesn't want to proceed.
  178.  */
  179. int warn_signatures(char *keyfile, long fp, int pktlen, char *userid,
  180.         boolean warn_only)
  181. {    FILE        *f;
  182.     byte        ctb;
  183.     long        fpusr;
  184.     int            usrpktlen;
  185.     byte        keyctrl;
  186.     int            trust_status = -1;
  187.  
  188.     keyctrl = KC_LEGIT_UNKNOWN;    /* Assume the worst */
  189.     PascalToC(userid);
  190.     if (getpubuserid (keyfile, fp, (byte *) userid, &fpusr, &usrpktlen) >= 0)
  191.     {    f = fopen(keyfile, "rb");
  192.         fseek (f, fpusr+usrpktlen, SEEK_SET);
  193.         /* Read trust byte */
  194.         trust_status = read_trust(f, &keyctrl);
  195.         fseek(f, fp, SEEK_SET);
  196.         if (is_compromised(f))
  197.         {
  198.             CToPascal(userid);
  199.             fprintf(pgpout, "\n");
  200.             show_key(f, fp, 0);
  201.             fclose (f);
  202.             fprintf(pgpout, PSTR("\007\nWARNING:  This key has been revoked by its owner,\n\
  203. possibly because the secret key was compromised.\n"));
  204.             if (warn_only)
  205.             {    /* this is only for checking signatures */
  206.                 fprintf(pgpout, PSTR("This could mean that this signature is a forgery.\n"));
  207.                 return(1);
  208.             }
  209.             else
  210.             {    /* don't use it for encryption */
  211.                 fprintf(pgpout, PSTR("You cannot use this revoked key.\n"));
  212.                 return(-1);
  213.             }
  214.         }
  215.         fclose (f);
  216.     }
  217.     CToPascal(userid);
  218.     if ((keyctrl & KC_LEGIT_MASK) != KC_LEGIT_COMPLETE)
  219.     {    byte userid0[256];
  220.         PascalToC(userid);
  221.         strcpy ((char *) userid0, userid);
  222.         CToPascal(userid);
  223.         if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_UNKNOWN)
  224.             fprintf(pgpout,PSTR("\007\nWARNING:  Because this public key is not certified with a trusted\n\
  225. signature, it is not known with high confidence that this public key\n\
  226. actually belongs to: \"%s\".\n"), EXTERNAL((char *)userid0));
  227.         if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_UNTRUSTED)
  228.             fprintf(pgpout, PSTR("\007\nWARNING:  This public key is not trusted to actually belong to:\n\
  229. \"%s\".\n"), EXTERNAL((char *)userid0));
  230.         if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_MARGINAL)
  231.             fprintf(pgpout,PSTR("\007\nWARNING:  Because this public key is not certified with enough trusted\n\
  232. signatures, it is not known with high confidence that this public key\n\
  233. actually belongs to: \"%s\".\n"), EXTERNAL((char *)userid0));
  234.         if (!filter_mode && !warn_only && !(keyctrl & KC_WARNONLY))
  235.         {    fprintf(pgpout,PSTR("\nAre you sure you want to use this public key (y/N)? "));
  236.             if (!getyesno('n'))
  237.                 return(-1);
  238.             if (trust_status == 0 && (f = fopen(keyfile, "r+b")) != NULL)
  239.             {    fseek (f, fpusr+usrpktlen, SEEK_SET);
  240.                 keyctrl |= KC_WARNONLY;
  241.                 write_trust(f, keyctrl);
  242.                 fclose(f);
  243.             }
  244.         }
  245.     }
  246.     return(0);
  247. }    /* warn_signatures */
  248.  
  249.  
  250. boolean legal_ctb(byte ctb)
  251. {    /* Used to determine if nesting should be allowed. */
  252.     boolean legal;
  253.     byte ctbtype;
  254.     if (!is_ctb(ctb))        /* not even a bonafide CTB */
  255.         return(FALSE);
  256.     /* Sure hope CTB internal bit definitions don't change... */
  257.     ctbtype = (ctb & CTB_TYPE_MASK) >> 2;
  258.     /* Only allow these CTB types to be nested... */
  259.     legal = (
  260.             (ctbtype==CTB_PKE_TYPE)
  261.         ||    (ctbtype==CTB_SKE_TYPE)
  262.         ||    (ctbtype==CTB_CERT_SECKEY_TYPE)
  263.         ||    (ctbtype==CTB_CERT_PUBKEY_TYPE)
  264.         ||    (ctbtype==CTB_LITERAL_TYPE)
  265.         ||    (ctbtype==CTB_COMPRESSED_TYPE)
  266.         ||  (ctbtype==CTB_CKE_TYPE)
  267.          );
  268.     return(legal);
  269. }    /* legal_ctb */
  270.  
  271.  
  272. /* Return nonzero if val doesn't match checkval, after printing a
  273.  * warning.
  274.  */
  275. int
  276. version_error(int val, int checkval)
  277. {    if (val != checkval)
  278.     {    fprintf (pgpout, PSTR(
  279. "\n\007Unsupported packet format - you need a newer version of PGP for this file.\n"));
  280.         return(1);
  281.     }
  282.     return(0);
  283. }
  284.  
  285. /*-------------------------------------------------------------------------*/
  286.  
  287.  
  288. int strong_pseudorandom(byte *buf, int bufsize)
  289. /*    
  290.     Reads IDEA random key and random number seed from file, cranks the
  291.     the seed through the idearand strong pseudorandom number generator,
  292.     and writes them back out.  This is used for generation of
  293.     cryptographically strong pseudorandom numbers.  This is mainly to
  294.     save the user the trouble of having to type in lengthy keyboard
  295.     sequences for generation of truly random numbers every time we want
  296.     to make a random session key.  This pseudorandom generator will only
  297.     work if the file containing the random seed exists and is not empty.
  298.     If it doesn't exist, it will be automatically created.  If it exists
  299.     and is empty or nearly empty, it will not be used.
  300. */
  301. {    char seedfile[MAX_PATH];    /* Random seed filename */
  302.     FILE *f;
  303.     byte key[IDEAKEYSIZE];
  304.     byte seed[IDEABLOCKSIZE];
  305.     int i;
  306.     word32 tstamp; byte *timestamp = (byte *) &tstamp;
  307.  
  308.     buildfilename(seedfile,RANDSEED_FILENAME);
  309.  
  310.     if (!file_exists(seedfile))    /* No seed file. Start one... */
  311.     {    f = fopen(seedfile,"wb");    /* open for writing binary */
  312.         if (f==NULL)    /* failed to create seedfile */
  313.             return(-1);    /* error: no random number seed file available */
  314.         fclose(f);    /* close new empty seed file */
  315.         /* kickstart the generator with true random numbers */
  316.         fprintf(pgpout,PSTR("Initializing random seed file..."));
  317.         randaccum(8*(sizeof(key)+sizeof(seed)));
  318.         for (i=1; i<sizeof(key); i++)
  319.             key[i] ^= randombyte();
  320.         for (i=0; i<sizeof(seed); i++)
  321.             seed[i] ^= randombyte();
  322.     }    /* seedfile does not exist */
  323.  
  324.     else    /* seedfile DOES exist.  Open it and read it. */
  325.     {    f = fopen(seedfile,"rb");    /* open for reading binary */
  326.         if (f==NULL)    /* did open fail? */
  327.             return(-1);    /* error: no random number seed file available */
  328.         /* read IDEA random generator key */
  329.         if (fread(key,1,sizeof(key),f) < sizeof(key))    /* empty file? */
  330.         {    /* Empty or nearly empty file means don't use it. */
  331.             fclose(f);
  332.             return(-1);    /* error: no random number seed file available */
  333.         }
  334.         else
  335.             fread(seed,1,sizeof(seed),f); /* read pseudorandom seed */
  336.         fclose(f);
  337.     }    /* seedfile exists */
  338.  
  339.  
  340.     /* Initialize, key, and seed the IDEA pseudorandom generator: */
  341.     get_timestamp(timestamp);    /* timestamp points to tstamp */
  342.     init_idearand(key, seed, tstamp);
  343.  
  344.     /* Note that the seed will be cycled thru IDEA before use */
  345.  
  346.     /* Now fill the user's buffer with gobbledygook... */
  347.     while (bufsize--)
  348.         *buf++ = idearand() ^ randombyte();
  349.  
  350.     /* now cover up evidence of what user got */
  351.     for (i=1; i<sizeof(key); i++)
  352.         key[i] ^= idearand() ^ randombyte();
  353.     for (i=0; i<sizeof(seed); i++)
  354.         seed[i] = idearand() ^ randombyte();
  355.  
  356.     close_idearand();    /* close IDEA random number generator */
  357.  
  358.     f = fopen(seedfile,"wb");    /* open for writing binary */
  359.     if (f==NULL)    /* did open fail? */
  360.         return(-1);    /* error: no random number seed file available */
  361.     /* Now at start of file again */
  362.     fwrite(key,1,sizeof(key),f);
  363.     fwrite(seed,1,sizeof(seed),f);
  364.     fclose(f);
  365.     burn(key);        /* burn sensitive data on stack */
  366.     burn(seed);        /* burn sensitive data on stack */
  367.     return(0);    /* normal return */
  368. }    /* strong_pseudorandom */
  369.  
  370.  
  371.  
  372. int make_random_ideakey(byte key[16])
  373. /*    Make a random IDEA key.  Returns its length (a constant). */
  374. {    int count;
  375.  
  376.     if (strong_pseudorandom(key, IDEAKEYSIZE) == 0)
  377.         return(IDEAKEYSIZE);
  378.  
  379.     fprintf(pgpout,PSTR("Preparing random session key..."));
  380.  
  381.     randaccum(IDEAKEYSIZE*8); /* get some random key bits */
  382.  
  383.     count=0;
  384.     while (++count <= IDEAKEYSIZE)
  385.         key[count] = randombyte();
  386.  
  387.     return(IDEAKEYSIZE);
  388.  
  389. }    /* make_random_ideakey */
  390.  
  391.  
  392. word32 getpastlength(byte ctb, FILE *f)
  393. /*    Returns the length of a packet according to the CTB and
  394.     the length field. */
  395. {    word32 length;
  396.     unsigned int llength;    /* length of length */
  397.     byte buf[8];
  398.  
  399.     fill0(buf,sizeof(buf));
  400.     length = 0L;
  401.     /* Use ctb length-of-length field... */
  402.     llength = ctb_llength(ctb);    /* either 1, 2, 4, or 8 */
  403.     if (llength==8)        /* 8 means no length field, assume huge length */
  404.         return(-1L);    /* return huge length */
  405.  
  406.     /* now read in the actual length field... */
  407.     if (fread((byteptr) buf,1,llength,f) < llength)
  408.         return (-2L); /* error -- read failure or premature eof */
  409.     /* convert length from external byteorder... */
  410.     if (llength==1)
  411.         length = (word32) buf[0];
  412.     if (llength==2)
  413.         length = (word32) fetch_word16(buf);
  414.     if (llength==4)
  415.         length = fetch_word32(buf);
  416.     return(length);
  417. }    /* getpastlength */
  418.  
  419.  
  420. /* Write a CTB with the appropriate length field.  If big is true,
  421.  * always use a four-byte length field.
  422.  */
  423. void write_ctb_len (FILE *f, byte ctb_type, word32 length, boolean big)
  424. {
  425.     int        llength, llenb;
  426.     byte    ctb;
  427.     byte    buf[4];
  428.     int        i;
  429.  
  430.     if (big || (length > 0xFFFFL))
  431.     {    llength = 4;
  432.         llenb = 2;
  433.     }
  434.     else if ((word16)length > 0xFF)
  435.     {    llength = 2;
  436.         llenb = 1;
  437.     }
  438.     else
  439.     {    llength = 1;
  440.         llenb = 0;
  441.     }
  442.     ctb = CTB_BYTE(ctb_type, llenb);
  443.     fwrite( &ctb, 1, 1, f );
  444.     /* convert length to external byteorder... */
  445.     if (llength==1)
  446.         buf[0] = length;
  447.     if (llength==2)
  448.         put_word16((word16) length, buf);
  449.     if (llength==4)
  450.         put_word32(length, buf);
  451.     fwrite( buf, 1, llength, f );
  452. } /* write_ctb_len */
  453.  
  454.  
  455. int idea_file(byte *ideakey, boolean decryp, FILE *f, FILE *g, word32 lenfile)
  456. /*    Use IDEA in cipher feedback (CFB) mode to encrypt or decrypt a file. 
  457.     The encrypted material starts out with a 64-bit random prefix, which
  458.     serves as an encrypted random CFB initialization vector, and
  459.     following that is 16 bits of "key check" material, which is a
  460.     duplicate of the last 2 bytes of the random prefix.  Encrypted key
  461.     check bytes detect if correct IDEA key was used to decrypt ciphertext.
  462. */
  463. {    int count;
  464.     word16 iv[4];
  465.     extern byte textbuf[DISKBUFSIZE];
  466. #define RAND_PREFIX_LENGTH 8
  467.  
  468.     /* init CFB key */
  469.     fill0(iv,sizeof(iv));    /* define initialization vector IV as 0 */
  470.     initcfb_idea(iv,ideakey,decryp);
  471.  
  472.     if (!decryp)    /* encrypt-- insert key check bytes */
  473.     {    /* There is a random prefix followed by 2 key check bytes */
  474.         int    i;
  475.  
  476.         for (i=0; i<RAND_PREFIX_LENGTH; ++i)
  477.                 textbuf[i] = randombyte();
  478.         /* key check bytes are simply duplicates of final 2 random bytes */
  479.         textbuf[i] = textbuf[i-2];    /* key check bytes for redundancy */
  480.         textbuf[i+1] = textbuf[i-1];
  481.  
  482.         ideacfb(textbuf,RAND_PREFIX_LENGTH+2);
  483.         fwrite(textbuf,1,RAND_PREFIX_LENGTH+2,g);
  484.     }
  485.     else    /* decrypt-- check for key check bytes */
  486.     {    /* See if the redundancy is present after the random prefix */
  487.         count = fread(textbuf,1,RAND_PREFIX_LENGTH+2,f);
  488.         lenfile -= count;
  489.         if (count==(RAND_PREFIX_LENGTH+2))
  490.         {    ideacfb(textbuf,RAND_PREFIX_LENGTH+2);
  491.             if ((textbuf[RAND_PREFIX_LENGTH] != textbuf[RAND_PREFIX_LENGTH-2])
  492.                 || (textbuf[RAND_PREFIX_LENGTH+1] != textbuf[RAND_PREFIX_LENGTH-1]))
  493.             {    return(-2);        /* bad key error */
  494.             }
  495.         }
  496.         else    /* file too short for key check bytes */
  497.             return(-3);        /* error of the weird kind */
  498.     }
  499.  
  500.  
  501.     do    /* read and write the whole file in CFB mode... */
  502.     {    count = (lenfile < DISKBUFSIZE) ? (int)lenfile : DISKBUFSIZE;
  503.         count = fread(textbuf,1,count,f);
  504.         lenfile -= count;
  505.         if (count>0)
  506.         {    ideacfb(textbuf,count);
  507.             fwrite(textbuf,1,count,g);
  508.         }
  509.         /* if text block was short, exit loop */
  510.     } while (count==DISKBUFSIZE);
  511.  
  512.     close_idea();    /* Clean up data structures */
  513.     burn(iv);        /* burn sensitive data on stack */
  514.     burn(textbuf);    /* burn sensitive data on stack */
  515.     return(0);    /* should always take normal return */
  516. }    /* idea_file */
  517.  
  518.  
  519. /* Checksum maintained as a running sum by read_mpi and write_mpi.
  520.  * The checksum is maintained based on the plaintext values being
  521.  * read and written.  To use it, store a 0 to it before doing a set
  522.  * of read_mpi's or write_mpi's.  Then read it aftwerwards.
  523.  */
  524. word16    mpi_checksum;
  525.  
  526. int read_mpi(unitptr r, FILE *f, boolean adjust_precision, boolean scrambled)
  527. /*    Read a mutiprecision integer from a file.
  528.     adjust_precision is TRUE iff we should call set_precision to the 
  529.     size of the number read in.
  530.     scrambled is TRUE iff field is encrypted (protects secret key fields).
  531.     Returns the bitcount of the number read in, or returns a negative
  532.     number if an error is detected.
  533. */
  534. {    byte buf[MAX_BYTE_PRECISION+2];
  535.     unsigned int count;
  536.     word16 bytecount,bitcount;
  537.  
  538.     mp_init(r,0);
  539.  
  540.     if ((count = fread(buf,1,2,f)) < 2)
  541.         return (-1); /* error -- read failure or premature eof */
  542.  
  543.     bitcount = fetch_word16(buf);
  544.     if (bits2units(bitcount) > global_precision)
  545.         return(-1);    /* error -- possible corrupted bitcount */
  546.  
  547.     bytecount = bits2bytes(bitcount);
  548.  
  549.     count = fread(buf+2,1,bytecount,f);
  550.     if (count < bytecount)
  551.         return(-1);    /* error -- premature eof */
  552.  
  553.     if (scrambled)    /* decrypt the field */
  554.         ideacfb(buf+2,bytecount);
  555.  
  556.     /* Update running checksum, in case anyone cares... */
  557.     mpi_checksum += checksum (buf, bytecount+2);
  558.  
  559.     /*    We assume that the bitcount prefix we read is an exact
  560.         bitcount, not rounded up to the next byte boundary.
  561.         Otherwise we would have to call mpi2reg, then call
  562.         countbits, then call set_precision, then recall mpi2reg
  563.         again.
  564.     */
  565.     if (adjust_precision && bytecount)
  566.     {    /* set the precision to that specified by the number read. */
  567.         set_precision(bits2units(bitcount+SLOP_BITS));
  568.         /* Now that precision is optimally set, call mpi2reg */
  569.     }
  570.  
  571.     mpi2reg(r,buf);    /* convert to internal format */
  572.     burn(buf);    /* burn sensitive data on stack */
  573.     return (bitcount);
  574. }    /* read_mpi */
  575.  
  576.  
  577.  
  578. void write_mpi(unitptr n, FILE *f, boolean scrambled)
  579. /*    Write a multiprecision integer to a file.
  580.     scrambled is TRUE iff we should scramble field on the way out,
  581.     which is used to protect secret key fields.
  582. */
  583. {    byte buf[MAX_BYTE_PRECISION+2];
  584.     short bytecount;
  585.     bytecount = reg2mpi(buf,n);
  586.     mpi_checksum += checksum (buf, bytecount+2);
  587.     if (scrambled)  /* encrypt the field, skipping over the bitcount */
  588.         ideacfb(buf+2,bytecount);
  589.     fwrite(buf,1,bytecount+2,f); 
  590.     burn(buf);    /* burn sensitive data on stack */
  591. }    /* write_mpi */
  592.  
  593.  
  594. /*======================================================================*/
  595.  
  596.  
  597. int get_header_info_from_file(char *infile,  byte *header, int count)
  598. /*    Reads the first count bytes from infile into header. */
  599. {    FILE *f;
  600.     fill0(header,count);
  601.     /* open file f for read, in binary (not text) mode...*/
  602.     if ((f = fopen(infile,"rb")) == NULL)
  603.         return(-1);
  604.     /* read Cipher Type Byte, and maybe more */
  605.     count = fread(header,1,count,f);
  606.     fclose(f);
  607.     return(count);    /* normal return */
  608. }    /* get_header_info_from_file */
  609.  
  610.  
  611. /* System clock must be broken if it isn't past this date: */
  612. #define REASONABLE_DATE ((unsigned long) 0x27804180L)  /* 91 Jan 01 00:00:00 */
  613.  
  614.  
  615. int make_signature_certificate(byte *certificate, MD5_CTX *MD, byte class,
  616.     unitptr n, unitptr d, unitptr p, unitptr q, unitptr u)
  617. /*    Constructs a signed message digest in a signature certificate.
  618.     Returns total certificate length in bytes, or returns negative
  619.     error status.
  620. */
  621. {
  622.     byte inbuf[MAX_BYTE_PRECISION], outbuf[MAX_BYTE_PRECISION];
  623.     byte mdpacket[17];
  624.     byte *mdbufptr;
  625.     int i,j,certificate_length,blocksize,bytecount;
  626.     word16 ske_length;
  627.     word32 tstamp; byte *timestamp = (byte *) &tstamp;
  628.     byte keyID[KEYFRAGSIZE];
  629.     byte val;
  630.     int mdlen = 5;    /* length of class plus timestamp, for adding to MD */
  631.  
  632.     /*    Note that RSA key must be at least big enough to encipher a
  633.         complete message digest packet in a single RSA block. */
  634.  
  635.     blocksize = countbytes(n)-1;    /* size of a plaintext block */
  636.     if (blocksize < 31)
  637.     {    fprintf(pgpout,"\n\007Error: RSA key length must be at least 256 bits.\n");
  638.         return(-1);
  639.     }
  640.  
  641.     get_timestamp(timestamp);    /* Timestamp when signature was made */
  642.     if (tstamp < REASONABLE_DATE) /* complain about bad time/date setting */
  643.     {    fprintf(pgpout,PSTR("\n\007Error: System clock/calendar is set wrong.\n"));
  644.         return(-1);
  645.     }
  646.     convert_byteorder(timestamp,4); /* convert to external form */
  647.  
  648.     /* Finish off message digest calculation with this information */
  649.     MD_addbuffer (MD, &class, 1, FALSE);
  650.     MD_addbuffer (MD, timestamp, 4, TRUE);
  651.  
  652. #ifdef XLOWFIRST    /* Assumes LSB-first order */
  653.     mdbufptr = MD->digest;    /* point at actual message digest */
  654.     for (i=0; i<sizeof(mdpacket)-1; i++)
  655.     {    mdpacket[i] = *mdbufptr++;
  656.     }
  657.     mdpacket[i] = MD5_ALGORITHM_BYTE;
  658. #else
  659.     /* Assumes MSB-first order */
  660.     mdpacket[0] = MD5_ALGORITHM_BYTE;
  661.     mdbufptr = MD->digest;    /* point at actual message digest */
  662.     for (i=1; i<sizeof(mdpacket); i++)
  663.     {    mdpacket[i] = *mdbufptr++;
  664.     }
  665. #endif
  666.     /* Pre-block mdpacket, and convert to INTERNAL byte order: */
  667.     preblock((unitptr)inbuf, mdpacket, sizeof(mdpacket), n, NULL);
  668.  
  669.     fprintf(pgpout,PSTR("Just a moment..."));    /* RSA will take a while. */
  670.     fflush(pgpout);
  671.  
  672.     /* do RSA signature calculation: */
  673.     rsa_decrypt((unitptr)outbuf,(unitptr)inbuf,d,p,q,u);
  674.  
  675.     /* bytecount does not include the 2 prefix bytes */
  676.     bytecount = reg2mpi(outbuf,(unitptr)outbuf); /* convert to external format */
  677.     /*    outbuf now contains a message digest in external byteorder 
  678.         form.  Now make a complete signature certificate from this.
  679.     */
  680.  
  681.     certificate_length = 0;
  682.  
  683.     /* SKE is Secret Key Encryption (signed).  Append CTB for signed msg. */
  684.     certificate[certificate_length++] = CTB_SKE;
  685.  
  686.     /* SKE packet length does not include itself or CTB prefix: */
  687.     ske_length = 1 + 1     /* version and mdlen byte */
  688.                 + mdlen        /* class, timestamp and validation period */ 
  689.                 + KEYFRAGSIZE + 1 + 1    /* Key ID and 2 algorithm bytes */
  690.                 + 2 + bytecount+2;    /* 2 MD bytes and RSA MPI w/bitcount */
  691.     put_word16((word16) ske_length, certificate+certificate_length);
  692.     certificate_length+=2;    /* advance past word */
  693.  
  694.     certificate[certificate_length++] = VERSION_BYTE;
  695.  
  696.     /* Begin fields that are included in MD calculation... */
  697.  
  698.     certificate[certificate_length++] =  mdlen;    /* mdlen is length of MD-extras */
  699.  
  700.     certificate[certificate_length++] =  class & 0xff;
  701.     mdlen--;    /* assume class byte always present */
  702.  
  703.     /* timestamp already in external format */
  704.     if (mdlen>0)
  705.     {    for (j=0; j<SIZEOF_TIMESTAMP; j++)
  706.         {    certificate[certificate_length++] =  timestamp[j];
  707.             mdlen--;
  708.         }
  709.     }
  710.  
  711.     /* if any bytes remain in mdlen, assume it's the validation period */
  712.     if (mdlen>0)
  713.     {    val = 0;    /* Validation period */
  714.         put_word16(val, certificate+certificate_length);
  715.         certificate_length+=2;    /* advance past word */
  716.         mdlen-=2;
  717.     }
  718.     /* hopefully, mdlen is now zero.  */
  719.  
  720.     /* ...end of fields that are included in MD calculation */
  721.  
  722.     /* Now append keyID... */
  723.     extract_keyID(keyID, n);    /* gets keyID */
  724.     for (i=0; i<KEYFRAGSIZE; i++)
  725.         certificate[certificate_length++] = keyID[i];
  726.  
  727.     certificate[certificate_length++] = RSA_ALGORITHM_BYTE;
  728.     certificate[certificate_length++] = MD5_ALGORITHM_BYTE;
  729.  
  730.     /* Now append first two bytes of message digest */
  731.     mdbufptr = MD->digest;
  732.     certificate[certificate_length++] = *mdbufptr++;
  733.     certificate[certificate_length++] = *mdbufptr++;
  734.  
  735.     /* Now append the RSA-signed message digest packet: */
  736.     for (i=0; i<bytecount+2; i++)
  737.         certificate[certificate_length++] = outbuf[i];
  738.  
  739.     fputc('.',pgpout);    /* Signal RSA signature completion. */
  740.  
  741.     burn(inbuf);    /* burn sensitive data on stack */
  742.     burn(outbuf);    /* burn sensitive data on stack */
  743.  
  744.     return(certificate_length);    /* return length of certificate in bytes */
  745.  
  746. }    /* make_signature_certificate */
  747.  
  748.  
  749. /*======================================================================*/
  750.  
  751.  
  752. int signfile(boolean nested, boolean separate_signature,
  753.         char *mcguffin, char *infile, char *outfile,
  754.         char lit_mode, char *literalfile)
  755. /*    Write an RSA-signed message digest of input file to specified
  756.     output file, and append input file to output file.
  757.     separate_signature is TRUE iff we should not append the 
  758.     plaintext to the output signature certificate.
  759.     If lit_mode is MODE_TEXT, we know the infile is in canonical form.
  760.     We create a CTB_LITERAL packet for the plaintext data.
  761. */
  762. {    
  763.     FILE *f;
  764.     FILE *g;
  765.     int certificate_length;    /* signature certificate length */
  766.     byte certificate[MAX_SIGCERT_LENGTH];
  767.     char lfile[MAX_PATH];
  768.     byte signature_class;
  769.  
  770.     {    /* temporary scope for some buffers */
  771.         word32 tstamp; byte *timestamp = (byte *) &tstamp;        /* key certificate timestamp */
  772.         byte userid[256];
  773.         char keyfile[MAX_PATH];
  774.         long fp;
  775.         int pktlen, status;
  776.         MD5_CTX MD;
  777.         byte keyID[KEYFRAGSIZE];
  778.         unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION];
  779.         unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
  780.  
  781.         set_precision(MAX_UNIT_PRECISION);    /* safest opening assumption */
  782.  
  783.         if (verbose)
  784.             fprintf(pgpout,PSTR("\nPlaintext file: %s, signature file: %s\n"),
  785.             infile,outfile);
  786.  
  787.         if (MDfile(&MD, infile) < 0)
  788.             return(-1);    /* problem with input file.  error return */
  789.  
  790.         userid[0] = '\0';
  791.         if (mcguffin)
  792.             strcpy((char *) userid,mcguffin);    /* Who we are looking for */
  793.  
  794.         if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
  795.                          userid, n, e, d, p, q, u) < 0)
  796.             return(-1);    /* problem with secret key file. error return. */
  797.  
  798.         extract_keyID(keyID, n);
  799.         buildfilename(keyfile,PUBLIC_KEYRING_FILENAME); /* use default pathname */
  800.         if ((status = getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen,
  801.                 keyID, timestamp, userid, n, e)) != 0)
  802.         {    if (status == 1)
  803.             {    PascalToC((char *) userid);
  804.                 fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n\
  805. has been revoked.  You cannot use this key.\n"), EXTERNAL((char *)userid));       /* same msg in signkey */
  806.             }
  807.             return(-1);    /* problem with public key file. error return. */
  808.         }
  809.  
  810.         if (lit_mode==MODE_TEXT) signature_class = SM_SIGNATURE_BYTE;
  811.         else signature_class = SB_SIGNATURE_BYTE;
  812.  
  813.         certificate_length = make_signature_certificate(certificate, &MD,
  814.             signature_class, n, d, p, q, u);
  815.         if (certificate_length < 0)
  816.             return(-1);    /* error return from make_signature_certificate() */
  817.     }    /* end of scope for some buffers */
  818.  
  819.     /* open file f for read, in binary (not text) mode...*/
  820. #ifdef VMS
  821.     if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
  822. #else /* VMS */
  823.     if ((f = fopen(infile,"rb")) == NULL)
  824. #endif /* VMS */
  825.     {    fprintf(pgpout,PSTR("\n\007Can't open plaintext file '%s'\n"),infile);
  826.         return(-1);
  827.     }
  828.  
  829.     /* open file g for write, in binary (not text) mode...*/
  830.     if ((g = fopen(outfile,"wb")) == NULL)
  831.     {    fprintf(pgpout,PSTR("\n\007Can't create signature file '%s'\n"),outfile);
  832.         fclose(f);
  833.         return(-1);
  834.     }
  835.  
  836.     /* write out certificate record to outfile ... */
  837.     fwrite(certificate,1,certificate_length,g);
  838.  
  839.     if (!separate_signature)
  840.     {    if (!nested)
  841.         {    word32 flen = fsize(f);
  842.             word32 dummystamp = 0;
  843.             write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
  844.             fwrite ( &lit_mode, 1, 1, g );    /*    write lit_mode */
  845.             /* write literalfile name */
  846.             if (literalfile == NULL)
  847.             {    /* Put in a zero byte to indicate no filename */
  848.                 fputc ('\0', g);
  849.             }
  850.             else
  851.             {    strcpy( lfile, literalfile );
  852.                 file_to_canon( lfile );
  853.                 CToPascal( lfile );
  854.                 fwrite ( lfile, 1, lfile[0]+1, g);
  855.             }
  856.             /* Dummy file creation timestamp */
  857.             fwrite ( &dummystamp, 1, sizeof(dummystamp), g);
  858.         }
  859.         copyfile(f,g,-1L);    /* copy rest of file from file f to g */
  860.     }
  861.  
  862.     fclose(g);
  863.     fclose(f);
  864.     return(0);    /* normal return */
  865.  
  866. }    /* signfile */
  867.  
  868.  
  869. /*======================================================================*/
  870.  
  871.  
  872. int compromise(char *keyguffin, char *keyfile)
  873. {    
  874.     FILE *f, *g;
  875.     byte ctb;    /* Cipher Type Byte */
  876.     int certificate_length;    /* signature certificate length */
  877.     byte certificate[MAX_SIGCERT_LENGTH];
  878.     byte keyID[KEYFRAGSIZE];
  879.     word32 tstamp; byte *timestamp = (byte *) &tstamp;
  880.     byte userid[256];
  881.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  882.     MD5_CTX MD;
  883.     unit d[MAX_UNIT_PRECISION];
  884.     unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
  885.     long fp, insertpos;
  886.     int pktlen;
  887.     int status, prec;
  888.  
  889.     if (build_path(SCRATCH_KEYRING_PATH,SCRATCH_KEYRING_FILENAME,keyfile)<0)
  890.         return(-1);        /* File path too long */
  891.  
  892.     strcpy((char *)userid, keyguffin);
  893.     if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
  894.                      userid, n, e, d, p, q, u) < 0)
  895.         return(-1);    /* problem with secret key file. error return. */
  896.  
  897.     extract_keyID(keyID, n);
  898.  
  899.     strcpy((char *)userid, keyguffin);
  900.  
  901.     if (getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen,
  902.             keyID, timestamp, userid, n, e) < 0)
  903.         return(-1);
  904.  
  905.     PascalToC((char *) userid);
  906.     fprintf(pgpout, 
  907. PSTR("\nDo you want to permanently revoke your public key\n\
  908. by issuing a secret key compromise certificate\n\
  909. for \"%s\" (y/N)? "), EXTERNAL((char *)userid));
  910.     if (!getyesno('n'))
  911.         return(-1);
  912.  
  913.     /* open file f for read, in binary (not text) mode...*/
  914.     if ((f = fopenbin(keyfile,"r")) == NULL)
  915.     {    fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
  916.         return(-1);
  917.     }
  918.  
  919.     fseek (f, fp+pktlen, SEEK_SET);
  920.     nextkeypacket(f, &ctb);
  921.     if (ctb == CTB_KEYCTRL)
  922.     {    insertpos = ftell(f);
  923.         nextkeypacket(f, &ctb);
  924.     }
  925.     else
  926.         insertpos = fp + pktlen;
  927.  
  928.     if (is_ctb_type(ctb, CTB_SKE_TYPE))
  929.     {
  930.         fprintf(pgpout, PSTR("This key has already been revoked.\n"));
  931.         fclose(f);
  932.         return(-1);
  933.     }
  934.  
  935.     prec = global_precision;
  936.     set_precision(MAX_UNIT_PRECISION);    /* safest opening assumption */
  937.  
  938.     fseek(f, fp, SEEK_SET);
  939.     /* Calculate signature */
  940.     if (MDfile0_len(&MD, f, pktlen) < 0)
  941.     {    fclose(f);
  942.         return(-1);    /* problem with input file.  error return */
  943.     }
  944.     set_precision(prec);
  945.  
  946.     certificate_length = make_signature_certificate(certificate, &MD,
  947.         KC_SIGNATURE_BYTE, n, d, p, q, u);
  948.     if (certificate_length < 0)
  949.     {    fclose(f);
  950.         return(-1);    /* error return from make_signature_certificate() */
  951.     }
  952.  
  953.  
  954.     /* open file g for write, in binary (not text) mode...*/
  955.     remove(SCRATCH_KEYRING_PATH);
  956.     if ((g = fopen(SCRATCH_KEYRING_PATH,"wb")) == NULL)
  957.     {    fprintf(pgpout,PSTR("\n\007Can't create output file to update key ring.\n"));
  958.         fclose(f);
  959.         return(-1);
  960.     }
  961.  
  962.     /* Copy pre-key and key to file g */
  963.     rewind(f);
  964.     copyfile (f, g, insertpos);
  965.  
  966.     /* write out certificate record to outfile ... */
  967.     fwrite(certificate,1,certificate_length,g);
  968.  
  969.     /* Copy the remainder from file f to file g */
  970.     copyfile (f, g, -1L);
  971.     
  972.     fflush(g);
  973.     if (ferror(g))
  974.     {    fclose(g);
  975.         return(-1);
  976.     }
  977.     fclose(g);
  978.  
  979.     backup_rename(SCRATCH_KEYRING_PATH,keyfile);
  980.  
  981.     fprintf(pgpout, PSTR("\nKey compromise certificate created.\n"));
  982.     return(0);    /* normal return */
  983. }    /* compromise */
  984.  
  985. /*======================================================================*/
  986.  
  987.  
  988. int signkey(char *keyguffin, char *sigguffin, char *keyfile)
  989. /*  Write an RSA-signed message digest of key for user keyguffin in
  990.     keyfile, using signature from user sigguffin.  Append
  991.     the signature right after the key.
  992. */
  993. {    
  994.     FILE *f;
  995.     FILE *g;
  996.     byte ctb;    /* Cipher Type Byte */
  997.     int certificate_length;    /* signature certificate length */
  998.     byte certificate[MAX_SIGCERT_LENGTH];
  999.     byte keyID[KEYFRAGSIZE], keyID2[KEYFRAGSIZE];
  1000.     word32 tstamp; byte *timestamp = (byte *) &tstamp;
  1001.     byte userid[256];
  1002.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  1003.     char pubring[MAX_PATH];
  1004.     long fp, fpusr;
  1005.     int pktlen, usrpktlen, usrctrllen;
  1006.     char *tempring;
  1007.     int status;
  1008.  
  1009.     /* Get signature key ID */
  1010.     strcpy((char *)userid,sigguffin);    /* Who we are looking for */
  1011.     if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
  1012.                      userid, n, e, NULL, NULL, NULL, NULL) < 0)
  1013.     {
  1014.         return(-1);    /* problem with secret key file. error return. */
  1015.     }
  1016.     extract_keyID(keyID, n);    /* Remember signer key ID */
  1017.     buildfilename(pubring,PUBLIC_KEYRING_FILENAME); /* use default pathname */
  1018.     if ((status = getpublickey(FALSE, FALSE, pubring, &fp, &pktlen,
  1019.             keyID, timestamp, userid, n, e)) != 0)
  1020.     {    if (status == 1)
  1021.         {    PascalToC((char *) userid);
  1022.             fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n\
  1023. has been revoked.  You cannot use this key.\n"), EXTERNAL((char *)userid));       /* same msg in signfile */
  1024.         }
  1025.         return(-1);    /* problem with public key file. error return. */
  1026.     }
  1027.  
  1028.     strcpy((char *)userid, keyguffin);
  1029.     fprintf(pgpout, PSTR("\nLooking for key for user '%s':\n"), EXTERNAL((char *)userid));
  1030.  
  1031.     if (getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen,
  1032.             NULL, timestamp, userid, n, e) < 0)
  1033.         return(-1);
  1034.     PascalToC((char *) userid);
  1035.     if (getpubuserid (keyfile, fp, (byte *)keyguffin, &fpusr, &usrpktlen) < 0)
  1036.         return(-1);
  1037.  
  1038.     /* open file f for read, in binary (not text) mode...*/
  1039. #ifdef VMS
  1040.     if ((f = fopen(keyfile,"rb","ctx=stm")) == NULL)
  1041. #else
  1042.     if ((f = fopen(keyfile,"rb")) == NULL)
  1043. #endif
  1044.     {    fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
  1045.         return(-1);
  1046.     }
  1047.  
  1048.     fseek(f, fp, SEEK_SET);
  1049.     if (is_compromised(f))
  1050.     {    fprintf(pgpout, PSTR("\n\007Sorry, this key has been revoked by its owner.\n"));
  1051.         fclose(f);
  1052.         return(-1);
  1053.     }
  1054.     /* See if there is another signature with this keyID already */
  1055.     fseek (f, fpusr+usrpktlen, SEEK_SET);
  1056.     nextkeypacket(f, &ctb);        /* Add key control packet to len */
  1057.     usrctrllen = 0;
  1058.     if (ctb != CTB_KEYCTRL)
  1059.         fseek(f,fpusr+usrpktlen,SEEK_SET);
  1060.     else
  1061.         usrctrllen = ftell(f) - (fpusr+usrpktlen);
  1062.     for ( ; ; )
  1063.     {    status = readkeypacket(f,FALSE,&ctb,NULL,NULL,NULL,NULL,
  1064.                     NULL,NULL,NULL,NULL,keyID2,NULL);
  1065.         if (status < 0  ||  is_key_ctb (ctb)  ||  ctb==CTB_USERID)
  1066.             break;
  1067.         if (equal_buffers(keyID, keyID2, KEYFRAGSIZE))
  1068.         {    fprintf(pgpout,PSTR("\n\007Key is already signed by user '%s'.\n"),
  1069.                 EXTERNAL(sigguffin));
  1070.             fclose(f);
  1071.             return(-1);
  1072.         }
  1073.     }
  1074.     rewind(f);
  1075.  
  1076.     fprintf(pgpout,
  1077. PSTR("\n\nREAD CAREFULLY:  Based on your own direct first-hand knowledge, are\n\
  1078. you absolutely certain that you are prepared to solemnly certify that\n\
  1079. the above public key actually belongs to the user specified by the\n\
  1080. above user ID (y/N)? "));
  1081.  
  1082.     if (!getyesno('n'))
  1083.     {    fclose(f);
  1084.         return(-1);
  1085.     }
  1086.  
  1087.     {    /* temporary scope for some buffers */
  1088.         MD5_CTX MD;
  1089.         unit d[MAX_UNIT_PRECISION];
  1090.         unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
  1091.  
  1092.         set_precision(MAX_UNIT_PRECISION);    /* safest opening assumption */
  1093.  
  1094.         if ((g = fopen(keyfile,"rb")) == NULL)
  1095.         {    fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
  1096.             return(-1);
  1097.         }
  1098.         fseek(g, fp, SEEK_SET);
  1099.         /* Calculate signature */
  1100.         if (MDfile0_len(&MD, g, pktlen) < 0)
  1101.         {    fclose(g);
  1102.             fclose(f);
  1103.             return(-1);    /* problem with input file.  error return */
  1104.         }
  1105.         fclose(g);
  1106.  
  1107.         /* Add data from user id */
  1108.         CToPascal((char *)userid);
  1109.         MD5Update(&MD, userid+1, (int)(unsigned char)userid[0]);
  1110.  
  1111.         strcpy((char *)userid,sigguffin);    /* Who we are looking for */
  1112.  
  1113.         if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
  1114.                          userid, n, e, d, p, q, u) < 0)
  1115.         {    fclose(f);
  1116.             return(-1);    /* problem with secret key file. error return. */
  1117.         }
  1118.  
  1119.         certificate_length = make_signature_certificate(certificate, &MD,
  1120.             K0_SIGNATURE_BYTE, n, d, p, q, u);
  1121.         if (certificate_length < 0)
  1122.             return(-1);    /* error return from make_signature_certificate() */
  1123.  
  1124.     }    /* end of scope for some buffers */
  1125.  
  1126.     /* open file g for write, in binary (not text) mode...*/
  1127.     tempring = tempfile(TMP_TMPDIR);
  1128.     if ((g = fopen(tempring,"wb")) == NULL)
  1129.     {    fprintf(pgpout,PSTR("\n\007Can't create output file to update key ring.\n"));
  1130.         fclose(f);
  1131.         return(-1);
  1132.     }
  1133.  
  1134.     /* Copy pre-key and key to file g */
  1135.     copyfile (f, g, fpusr+usrpktlen+usrctrllen);
  1136.  
  1137.     /* write out certificate record to outfile ... */
  1138.     fwrite(certificate,1,certificate_length,g);
  1139.  
  1140.     /* Add "trusty" control packet */
  1141.     write_trust (g, KC_SIGTRUST_ULTIMATE | KC_CONTIG);
  1142.  
  1143.     /* Copy the remainder from file f to file g */
  1144.     copyfile (f, g, -1L);
  1145.     
  1146.     fclose(g);
  1147.     fclose(f);
  1148.  
  1149.     savetempbak(tempring,keyfile);
  1150.  
  1151.     fprintf(pgpout, PSTR("\nKey signature certificate added.\n"));
  1152.     return(0);    /* normal return */
  1153.  
  1154. }    /* signkey */
  1155.  
  1156.  
  1157. /*======================================================================*/
  1158.  
  1159. int check_signaturefile(char *infile, char *outfile, boolean strip_signature,
  1160.             boolean explicit_outfile_flag)
  1161. {    /* Check signature in infile for validity.  Strip off the signature
  1162.        and write the remaining packet to outfile.  If strip_signature,
  1163.        also write the signature to outfile.sig.  If the packet after
  1164.        the signature is a LITERAL2, use the filename from there unless
  1165.        explict_outfile_flag is set.
  1166.     */
  1167.     byte ctb,ctb2;    /* Cipher Type Bytes */
  1168.     char keyfile[MAX_PATH];    /* for getpublickey */
  1169.     char sigfile[MAX_PATH]; /* .sig file if strip_signature */
  1170.     long fp;    /* unused, just to satisfy getpublickey */
  1171.     int pktlen;    /* unused, just to satisfy getpublickey */
  1172.     FILE *f;
  1173.     FILE *g;
  1174.     long start_text;    /* marks file position */
  1175.     int i,count;
  1176.     word16 cert_length;
  1177.     byte certbuf[MAX_SIGCERT_LENGTH];
  1178.     byteptr certificate; /* for parsing certificate buffer */
  1179.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  1180.     byte inbuf[MAX_BYTE_PRECISION];
  1181.     byte outbuf[MAX_BYTE_PRECISION];
  1182.     byte keyID[KEYFRAGSIZE];
  1183.     word32 tstamp;
  1184.     byte *timestamp = (byte *) &tstamp;        /* key certificate timestamp */
  1185.     word32 dummystamp;
  1186.     byte userid[256];
  1187.     MD5_CTX MD;
  1188.     boolean separate_signature;
  1189.     extern boolean moreflag;
  1190.     char lit_mode = MODE_BINARY;
  1191.     unsigned char litfile[MAX_PATH];
  1192.     word32 text_len;
  1193.     byte    *mdextras;
  1194.     byte    mdlensave;
  1195.     byte    version;
  1196.     byte    mdlen;    /* length of material to be added to MD calculation */
  1197.     byte    class;
  1198.     byte    algorithm;
  1199.     byte    mdlow2[2];
  1200.  
  1201.     fill0( keyID, KEYFRAGSIZE );
  1202.  
  1203.     set_precision(MAX_UNIT_PRECISION);    /* safest opening assumption */
  1204.  
  1205.     buildfilename(keyfile,PUBLIC_KEYRING_FILENAME); /* use default pathname */
  1206.  
  1207.     if (verbose)
  1208.         fprintf(pgpout,PSTR("\nSignature file: %s, output file: %s\n"),
  1209.         infile,outfile);
  1210.  
  1211.     /* open file f for read, in binary (not text) mode...*/
  1212. #ifdef VMS
  1213.     if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
  1214. #else
  1215.     if ((f = fopen(infile,"rb")) == NULL)
  1216. #endif /* VMS */
  1217.     {    fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),infile);
  1218.         return(-1);
  1219.     }
  1220.  
  1221.     /******************** Read header CTB and length field ******************/
  1222.  
  1223.     fread(&ctb,1,1,f);    /* read certificate CTB byte */
  1224.     certificate = certbuf;
  1225.     *certificate++ = ctb;    /* copy ctb into certificate */
  1226.  
  1227.     if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_SKE_TYPE))
  1228.         goto badcert;    /* complain and return bad status */
  1229.  
  1230.     cert_length = getpastlength(ctb, f); /* read certificate length */
  1231.     certificate += ctb_llength(ctb);    /* either 1, 2, 4, or 8 */
  1232.     if (cert_length > MAX_SIGCERT_LENGTH-3)    /* Huge packet length */
  1233.         goto badcert;    /* complain and return bad status */
  1234.  
  1235.     /* read whole certificate: */
  1236.     if (fread((byteptr) certificate, 1, cert_length, f) < cert_length)
  1237.         /* bad packet length field */
  1238.         goto badcert;    /* complain and return bad status */
  1239.  
  1240.     version = *certificate++;
  1241.     if (version_error(version, VERSION_BYTE))
  1242.         goto err1;
  1243.  
  1244.     mdlensave = mdlen = *certificate++;    /* length of material to be added to MD */
  1245.     mdextras = certificate;    /* pointer to extra material for MD calculation */
  1246.  
  1247.     class = *certificate++;
  1248.     if (class != SM_SIGNATURE_BYTE  &&  class != SB_SIGNATURE_BYTE)
  1249.     {    (void) version_error(class, SM_SIGNATURE_BYTE);
  1250.         goto err1;
  1251.     }
  1252.     mdlen--;
  1253.  
  1254.     if (mdlen>0)    /* if more MD material is included... */
  1255.     {    for (i=0; i<SIZEOF_TIMESTAMP; ++i)
  1256.         {    timestamp[i] = *certificate++;
  1257.             mdlen--;
  1258.         }
  1259.     }
  1260.     
  1261.     if (mdlen>0)    /* if more MD material is included... */
  1262.     {    certificate+=2;    /* skip past unused validity period field */
  1263.         mdlen-=2;
  1264.     }
  1265.  
  1266.     for (i=0; i<KEYFRAGSIZE; i++)
  1267.         keyID[i] = *certificate++; /* copy rest of key fragment */
  1268.  
  1269.     algorithm = *certificate++;
  1270.     if (version_error(algorithm, RSA_ALGORITHM_BYTE))
  1271.         goto err1;
  1272.  
  1273.     algorithm = *certificate++;
  1274.     if (version_error(algorithm, MD5_ALGORITHM_BYTE))
  1275.         goto err1;
  1276.  
  1277.     mdlow2[0] = *certificate++;
  1278.     mdlow2[1] = *certificate++;
  1279.  
  1280.     /* We used to set precision here based on certificate, but it is
  1281.     better to use the value based on n, since that was used when we
  1282.     signed the message.  The certificate length could be less than n's
  1283.     length.  We will call getpublickey here just to set the precision.
  1284.     */
  1285.     (void)getpublickey(FALSE, verbose, keyfile, &fp, &pktlen,
  1286.             keyID, (byte *)&dummystamp, userid, n, e);
  1287.  
  1288.     mpi2reg((unitptr)inbuf,certificate);    /* get signed message digest */
  1289.     certificate += countbytes((unitptr)inbuf)+2;
  1290.  
  1291.     if ((certificate-certbuf) != cert_length+3)
  1292.         /*    Bad length in signature certificate.  Off by 
  1293.             ((certificate-certbuf) - (cert_length+3)) */
  1294.         goto badcert;    /* complain and return bad status */
  1295.  
  1296.     start_text = ftell(f);    /* mark position of text for later */
  1297.  
  1298.     if (fread(outbuf,1,1,f) < 1)    /* see if any plaintext is there */
  1299.     {    /*    Signature certificate has no plaintext following it.
  1300.             Must be in another file.  Go look. */
  1301.         separate_signature = TRUE;
  1302.         fclose(f);
  1303.         fprintf(pgpout,PSTR("\nFile '%s' has signature, but with no text."),infile);
  1304.         if (!file_exists(outfile))
  1305.             force_extension(outfile, "");
  1306.         if (file_exists(outfile))
  1307.         {    fprintf(pgpout,PSTR("\nText is assumed to be in file '%s'.\n"),outfile);
  1308.         }
  1309.         else
  1310.         {    fprintf(pgpout,PSTR("\nPlease enter filename of text that signature applies to: "));
  1311.             getstring(outfile,59,TRUE);    /* echo keyboard */
  1312.             if ((int)strlen(outfile) == 0)
  1313.                 return(-1);
  1314.         }
  1315.         /* open file f for read, in binary (not text) mode...*/
  1316. #ifdef VMS
  1317.         if ((f = fopen(outfile,"rb","ctx=stm")) == NULL)
  1318. #else /* VMS */
  1319.         if ((f = fopen(outfile,"rb")) == NULL)
  1320. #endif /* VMS */
  1321.         {    fprintf(pgpout,PSTR("\n\007Can't open file '%s'\n"),outfile);
  1322.             return(-1);
  1323.         }
  1324.         start_text = ftell(f);    /* mark position of text for later */
  1325.         text_len = fsize(f);    /* remember length of text */
  1326.     }    /* had to open new input file */
  1327.     else
  1328.     {    separate_signature = FALSE;
  1329.         /*    We just read 1 byte, so outbuf[0] should contain a ctb, 
  1330.             maybe a CTB_LITERAL byte. */
  1331.         ctb2 = outbuf[0];
  1332.         if (is_ctb(ctb2) && is_ctb_type(ctb2,CTB_LITERAL_TYPE))
  1333.         {    /* Read literal data */
  1334.             text_len = getpastlength(ctb2, f); /* read packet length */
  1335.             lit_mode = '\0';
  1336.             fread (&lit_mode,1,1,f);    /* get literal packet mode byte */
  1337.             if (lit_mode != MODE_TEXT && lit_mode != MODE_BINARY)
  1338.             {    fprintf(pgpout,"\n\007Error: Illegal mode byte %02x in literal packet.\n",
  1339.                     lit_mode);    /* English-only diagnostic for debugging */
  1340.                 (void) version_error(lit_mode, MODE_BINARY);
  1341.                 goto err1;
  1342.             }
  1343.             if (verbose)
  1344.                 fprintf(pgpout, PSTR("File type: '%c'\n"), lit_mode);
  1345.             /* Read literal file name, use it if possible */
  1346.             litfile[0] = 0;
  1347.             fread (litfile,1,1,f);
  1348.             if ((int)litfile[0] > MAX_PATH)
  1349.                 litfile[0] = 0;    /* If too long for us, ignore it */
  1350.             if (litfile[0] > 0)
  1351.                 fread (litfile+1,1,litfile[0],f);
  1352.             /* Use litfile if it's writeable and he didn't say an outfile */
  1353.             if (litfile[0] > 0)
  1354.             {    PascalToC( (char *)litfile );
  1355.                 if (verbose)
  1356.                     fprintf(pgpout, PSTR("Original plaintext file name was: '%s'\n"), litfile);
  1357.                 if (!strcmp((char *) litfile, CONSOLE_FILENAME) || !explicit_outfile_flag)
  1358.                 {    file_from_canon( (char *)litfile );
  1359.                     if (file_ok_write( (char *)litfile ))
  1360.                         strcpy ( outfile, (char *)litfile );
  1361.                 }
  1362.             }
  1363.             /* Discard file creation timestamp for now */
  1364.             fread (&dummystamp, 1, sizeof(dummystamp), f);
  1365.             start_text = ftell(f);    /* mark position of text for later */
  1366.         }    /* packet is CTB_LITERAL_TYPE */
  1367.     }
  1368.  
  1369.     /* Use keyID prefix to look up key... */
  1370.  
  1371.     /*    Get and validate public key from a key file: */
  1372.     if (getpublickey(FALSE, verbose, keyfile, &fp, &pktlen,
  1373.             keyID, (byte *)&dummystamp, userid, n, e) < 0)
  1374.     {    /* Can't get public key.  Complain and process file copy anyway. */
  1375.         fprintf(pgpout,PSTR("\n\007WARNING: Can't find the right public key-- can't check signature integrity.\n"));
  1376.         goto outsig;
  1377.     }    /* Can't find public key */
  1378.  
  1379.     if (warn_signatures(keyfile, fp, pktlen, (char *)userid, TRUE) < 0)
  1380.         goto err1;
  1381.  
  1382.     /* Recover message digest via public key */
  1383.     mp_modexp((unitptr)outbuf,(unitptr)inbuf,e,n);
  1384.  
  1385.     fputc('.',pgpout);    /* Signal RSA completion. */
  1386.  
  1387.     /* Unblock message digest, and convert to external byte order: */
  1388.     count = postunblock(outbuf, (unitptr)outbuf, n);
  1389.     if (count < 0)
  1390.     {    fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
  1391. This may be caused either by corrupted data or by using the wrong RSA key.\n"));
  1392.         goto outsig;    /* Output data anyway */
  1393.     }
  1394.  
  1395.     /* outbuf should contain message digest packet */
  1396.     /*==================================================================*/
  1397.     /* Look at nested stuff within RSA block... */
  1398.  
  1399. #ifdef XLOWFIRST
  1400.     /* Position of algorithm byte assumes LSB-first byteorder... */
  1401.     if (outbuf[count-1] != MD5_ALGORITHM_BYTE)
  1402. #else
  1403.     /* Position of algorithm byte assumes MSB-first byteorder... */
  1404.     if (outbuf[0] != MD5_ALGORITHM_BYTE)
  1405. #endif
  1406.     {    fprintf(pgpout,PSTR("\007\nUnrecognized message digest algorithm.\n"));
  1407.         fprintf(pgpout,PSTR("This may require a newer version of PGP.\n"));
  1408.         fprintf(pgpout,PSTR("Can't check signature integrity.\n"));
  1409.         goto outsig;    /* Output data anyway */
  1410.     }
  1411.  
  1412. #ifdef XLOWFIRST
  1413.     if (outbuf[0] != mdlow2[0]  ||  outbuf[1] != mdlow2[1])
  1414. #else
  1415.     if (outbuf[1] != mdlow2[0]  ||  outbuf[2] != mdlow2[1])
  1416. #endif
  1417.     {    fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
  1418. This may be caused either by corrupted data or by using the wrong RSA key.\n"));
  1419.         goto outsig;    /* Output data anyway */
  1420.     }
  1421.  
  1422.     /* Reposition file to where that plaintext begins... */
  1423.     fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */
  1424.  
  1425.     MDfile0_len(&MD,f,text_len);/* compute a message digest from rest of file */
  1426.  
  1427.     MD_addbuffer (&MD, mdextras, mdlensave, TRUE); /* Finish message digest */
  1428.  
  1429.     convert_byteorder(timestamp,4); /* convert timestamp from external form */
  1430.     PascalToC((char *)userid);    /* for display */
  1431.  
  1432.     /* now compare computed MD with claimed MD */
  1433. #ifdef XLOWFIRST
  1434.     if (!equal_buffers((byte *)(MD.digest), outbuf, 16))
  1435. #else
  1436.     if (!equal_buffers((byte *)(MD.digest), outbuf+1, 16))
  1437. #endif
  1438.     {    fprintf(pgpout,PSTR("\007\nWARNING: Bad signature, doesn't match file contents!\007\n"));
  1439.         fprintf(pgpout,PSTR("\nBad signature from user \"%s\".\n"),EXTERNAL((char *)userid));
  1440.         fprintf(pgpout,PSTR("Signature made %s\n"),ctdate((word32 *)timestamp));
  1441. #ifndef CANONICAL_TEXT    /* native text format is not canonical text */
  1442.         /*    NOTE:  IF the signature is bad, AND this machine does not 
  1443.             use MSDOS-style canonical text as its native text format, 
  1444.             AND this is a detached signature certificate, AND this 
  1445.             file appears to contain ASCII text, THEN maybe we should 
  1446.             convert the file to canonical text form and try checking 
  1447.             the signature again.  
  1448.             This is because a detached signature certificate probably 
  1449.             means the file is not currently in a canonical text packet, 
  1450.             but it may have been in canonical text form when the 
  1451.             signature was created.
  1452.         */
  1453.         if (class == SM_SIGNATURE_BYTE && separate_signature)
  1454.         {    if (is_text_file(outfile))
  1455.                 fprintf(pgpout,PSTR("\n\007PGP may have problems checking signatures against text files\n\
  1456. if the text was created on a different system with a different\n\
  1457. text file format.\n"));
  1458.             /* Unfortunately, we don't give the user a way to convert it. */
  1459.         }
  1460. #endif    /* not CANONICAL_TEXT */
  1461.         if (moreflag)
  1462.         {    /* more will scroll the message off the screen */
  1463.             fprintf(pgpout, PSTR("\nPress ENTER to continue..."));
  1464.             fflush(pgpout);
  1465.             getyesno('n');
  1466.         }
  1467.         goto outsig;    /* Output data anyway */
  1468.     }
  1469.  
  1470.     fprintf(pgpout,PSTR("\nGood signature from user \"%s\".\n"),EXTERNAL((char *)userid));
  1471.     fprintf(pgpout,PSTR("Signature made %s\n"),ctdate((word32 *)timestamp));
  1472.  
  1473. outsig:
  1474.     /* Reposition file to where that plaintext begins... */
  1475.     fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */
  1476.  
  1477.     if (separate_signature)
  1478.         fprintf(pgpout,PSTR("\nSignature and text are separate.  No output file produced. "));
  1479.     else    /* signature precedes plaintext in file... */
  1480.     {    /* produce a plaintext output file from signature file */
  1481.         if (file_exists(outfile))
  1482.         {    fprintf(pgpout,PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "),outfile);
  1483.             if (!getyesno('n'))    /* user said don't do it. */
  1484.                 goto err1;    /* abort operation */
  1485.         }
  1486.         /* open file g for write, in binary or text mode...*/
  1487. #ifdef CANONICAL_TEXT
  1488.         if ((g = fopen(outfile,"wb")) == NULL)
  1489. #else
  1490.         if ((g = fopen(outfile,(lit_mode==MODE_BINARY)?"wb":"w")) == NULL)
  1491. #endif
  1492.         {    fprintf(pgpout,PSTR("\n\007Can't create plaintext file '%s'\n"),outfile);
  1493.             goto err1;
  1494.         }
  1495.         CONVERSION = (lit_mode == MODE_TEXT) ? EXT_CONV : NO_CONV;
  1496. #ifdef CANONICAL_TEXT
  1497.         copyfile(f,g,-1L);    /* copy rest of file from file f to g */
  1498. #else
  1499.         if (lit_mode == MODE_BINARY)
  1500.             copyfile( f, g, -1L );
  1501.         else
  1502.             copyfile_from_canon( f, g, -1L );
  1503. #endif
  1504.         CONVERSION = NO_CONV;
  1505.  
  1506.         fclose(g);
  1507.         
  1508.         if (strip_signature)
  1509.         {    /* Copy signature to a .sig file */
  1510.             strcpy (sigfile, outfile);
  1511.             force_extension(sigfile,SIG_EXTENSION);
  1512.             if (file_exists(sigfile))
  1513.             {    fprintf(pgpout,PSTR("\n\007Signature file '%s' already exists.  Overwrite (y/N)? "),sigfile);
  1514.                 if (!getyesno('n'))
  1515.                     goto err1;
  1516.             }
  1517.             if ((g = fopen(sigfile,"wb")) == NULL)
  1518.             {    fprintf(pgpout,PSTR("\n\007Can't create signature file '%s'\n"),sigfile);
  1519.                 goto err1;
  1520.             }
  1521.             fseek (f,0L,SEEK_SET);
  1522.             copyfile (f,g,(unsigned long)(cert_length+ctb_llength(ctb)+1));
  1523.             fclose(g);
  1524.             fprintf(pgpout,PSTR("\nWriting signature certificate to '%s'\n"),sigfile);
  1525.         }
  1526.     }
  1527.  
  1528.     burn(inbuf);    /* burn sensitive data on stack */
  1529.     burn(outbuf);    /* burn sensitive data on stack */
  1530.     fclose(f);
  1531.     if (separate_signature)
  1532.     {    *outfile = '\0';
  1533.         return(0);    /* normal return, no nested info */
  1534.     }
  1535.     if (is_ctb(ctb2) && (is_ctb_type(ctb2,CTB_LITERAL_TYPE)))
  1536.         /* we already stripped away the CTB_LITERAL */
  1537.         return(0);    /* normal return, no nested info */
  1538.     /* Otherwise, it's best to assume a nested CTB */
  1539.     return(1);    /* nested information return */
  1540.  
  1541. badcert:    /* Bad packet.  Complain. */
  1542.     fprintf(pgpout,PSTR("\n\007Error: Badly-formed or corrupted signature certificate.\n"));
  1543.     fprintf(pgpout,PSTR("File \"%s\" does not have a properly-formed signature.\n"),infile);
  1544.     /* Now just drop through to error exit... */
  1545.  
  1546. err1:
  1547.     burn(inbuf);    /* burn sensitive data on stack */
  1548.     burn(outbuf);    /* burn sensitive data on stack */
  1549.     fclose(f);
  1550.     return(-1);    /* error return */
  1551.  
  1552. }    /* check_signaturefile */
  1553.  
  1554.  
  1555. int check_key_sig(FILE *fkey, long fpkey, int keypktlen, char *keyuserid,
  1556.      FILE *fsig, long fpsig, char *keyfile, char *siguserid, byte *xtimestamp,
  1557.      byte *sigclass)
  1558. {    /* Check signature of key in file fkey at position fpkey, using signature
  1559.        in file fsig and position fpsig.  keyfile tells the file to use to
  1560.        look for the public key in to check the sig.  Return 0 if OK, -1 if
  1561.        we can't check the signature, -2 if bad or other problem.
  1562.     */
  1563.     byte ctb;    /* Cipher Type Bytes */
  1564.     long fp;    /* unused, just to satisfy getpublickey */
  1565.     int pktlen;    /* unused, just to satisfy getpublickey */
  1566.     word16 cert_length;
  1567.     int i, count;
  1568.     byte certbuf[MAX_SIGCERT_LENGTH];
  1569.     byteptr certificate; /* for parsing certificate buffer */
  1570.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  1571.     byte inbuf[MAX_BYTE_PRECISION];
  1572.     byte outbuf[MAX_BYTE_PRECISION];
  1573.     byte keyID[KEYFRAGSIZE];
  1574.     MD5_CTX MD;
  1575.     byte mdlensave;
  1576.     byte *mdextras;
  1577.     word32 tstamp;
  1578.     byte *timestamp = (byte *) &tstamp;        /* key certificate timestamp */
  1579.     byte    version;
  1580.     byte    mdlen;    /* length of material to be added to MD calculation */
  1581.     byte    class;
  1582.     byte    algorithm;
  1583.     byte    mdlow2[2];
  1584.  
  1585.     fill0( keyID, KEYFRAGSIZE );
  1586.  
  1587.     set_precision(MAX_UNIT_PRECISION);    /* safest opening assumption */
  1588.  
  1589.     /******************** Read header CTB and length field ******************/
  1590.  
  1591.     fseek(fsig, fpsig, SEEK_SET);
  1592.     fread(&ctb,1,1,fsig);    /* read certificate CTB byte */
  1593.     certificate = certbuf;
  1594.     *certificate++ = ctb;    /* copy ctb into certificate */
  1595.  
  1596.     if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_SKE_TYPE))
  1597.         goto badcert2;    /* complain and return bad status */
  1598.  
  1599.     cert_length = getpastlength(ctb, fsig); /* read certificate length */
  1600.     certificate += ctb_llength(ctb);    /* either 1, 2, 4, or 8 */
  1601.     if (cert_length > MAX_SIGCERT_LENGTH-3)    /* Huge packet length */
  1602.         goto badcert2;    /* complain and return bad status */
  1603.  
  1604.     /* read whole certificate: */
  1605.     if (fread((byteptr) certificate, 1, cert_length, fsig) < cert_length)
  1606.         /* bad packet length field */
  1607.         goto badcert2;    /* complain and return bad status */
  1608.  
  1609.     version = *certificate++;
  1610.     if (version_error(version, VERSION_BYTE))
  1611.         goto err2;
  1612.  
  1613.     mdlensave = mdlen = *certificate++;    /* length of material to be added to MD */
  1614.     mdextras = certificate;    /* pointer to extra material for MD calculation */
  1615.  
  1616.     *sigclass = class = *certificate++;
  1617.     if (class != K0_SIGNATURE_BYTE  &&  class != K1_SIGNATURE_BYTE &&
  1618.         class != K2_SIGNATURE_BYTE  &&  class != K3_SIGNATURE_BYTE &&
  1619.         class != KC_SIGNATURE_BYTE)
  1620.     {    (void) version_error(class, K0_SIGNATURE_BYTE);
  1621.         goto err2;
  1622.     }
  1623.     mdlen--;
  1624.  
  1625.     if (mdlen>0)    /* if more MD material is included... */
  1626.     {    for (i=0; i<SIZEOF_TIMESTAMP; ++i)
  1627.         {    timestamp[i] = *certificate++;
  1628.             mdlen--;
  1629.         }
  1630.     }
  1631.  
  1632.     if (mdlen>0)    /* if more MD material is included... */
  1633.     {    certificate+=2;    /* skip past unused validity period word */
  1634.         mdlen-=2;
  1635.     }
  1636.  
  1637.     if (mdlen>0)    /* if more MD material is included... */
  1638.         certificate+=mdlen;    /* skip over the rest */
  1639.  
  1640.     for (i=0; i<KEYFRAGSIZE; i++)
  1641.         keyID[i] = *certificate++; /* copy rest of key fragment */
  1642.  
  1643.     algorithm = *certificate++;
  1644.     if (version_error(algorithm, RSA_ALGORITHM_BYTE))
  1645.         goto err2;
  1646.  
  1647.     algorithm = *certificate++;
  1648.     if (version_error(algorithm, MD5_ALGORITHM_BYTE))
  1649.         goto err2;
  1650.  
  1651.     /* Grab 1st 2 bytes of message digest */
  1652.     mdlow2[0] = *certificate++;
  1653.     mdlow2[1] = *certificate++;
  1654.  
  1655.     /* We used to set precision here based on certificate value,
  1656.      * but it was sometimes less than that based on n.  Read public
  1657.      * key here to set precision, before we go on.
  1658.      */
  1659.     /* This sets precision, too, based on n. */
  1660.     if (getpublickey(TRUE, FALSE, keyfile, &fp, &pktlen,
  1661.             keyID, xtimestamp, (unsigned char *)siguserid, n, e) < 0)
  1662.         goto err1;
  1663.  
  1664.     mpi2reg((unitptr)inbuf,certificate);    /* get signed message digest */
  1665.     certificate += countbytes((unitptr)inbuf)+2;
  1666.  
  1667.     if ((certificate-certbuf) != cert_length+3)
  1668.         /*    Bad length in signature certificate.  Off by 
  1669.             ((certificate-certbuf) - (cert_length+3)) */
  1670.         goto badcert2;    /* complain and return bad status */
  1671.  
  1672.     /* Recover message digest via public key */
  1673.     mp_modexp((unitptr)outbuf,(unitptr)inbuf,e,n);
  1674.  
  1675.     /* Unblock message digest, and convert to external byte order: */
  1676.     if ((count = postunblock(outbuf, (unitptr)outbuf, n)) < 0)
  1677.         goto err2;    /* Bad RSA decrypt.  Corruption, or wrong key. */
  1678.  
  1679.     /* outbuf should contain message digest packet */
  1680.     /*==================================================================*/
  1681.     /* Look at nested stuff within RSA block... */
  1682.  
  1683. #ifdef XLOWFIRST    /* assumes LSB-first */
  1684.     if (outbuf[count-1] != MD5_ALGORITHM_BYTE)
  1685.         goto err2;    /* Bad RSA decrypt.  Corruption, or wrong key. */
  1686.     if (outbuf[0] != mdlow2[0]  ||  outbuf[1] != mdlow2[1])
  1687.         goto err2;    /* Bad RSA decrypt.  Corruption, or wrong key. */
  1688. #else
  1689.     if (outbuf[0] != MD5_ALGORITHM_BYTE)
  1690.         goto err2;    /* Bad RSA decrypt.  Corruption, or wrong key. */
  1691.     if (outbuf[1] != mdlow2[0]  ||  outbuf[2] != mdlow2[1])
  1692.         goto err2;    /* Bad RSA decrypt.  Corruption, or wrong key. */
  1693. #endif
  1694.  
  1695.     /* Position file to where that plaintext begins... */
  1696.     fseek(fkey,fpkey,SEEK_SET);
  1697.  
  1698.     /* compute a message digest from key packet */
  1699.     MDfile0_len(&MD,fkey,keypktlen);
  1700.     /* Add data from user id */
  1701.     if (class != KC_SIGNATURE_BYTE)
  1702.         MD5Update(&MD, (unsigned char *) keyuserid+1, (int)(unsigned char)keyuserid[0]);
  1703.     /* Add time and class data */
  1704.     MD_addbuffer (&MD, mdextras, mdlensave, TRUE);    /* Finish message digest */
  1705.  
  1706.     /* now compare computed MD with claimed MD */
  1707. #ifdef XLOWFIRST    /* assumes LSB-first */
  1708.     if (!equal_buffers((byte *)(MD.digest), outbuf, 16))
  1709.     goto err2;
  1710. #else
  1711.     if (!equal_buffers((byte *)(MD.digest), outbuf+1, 16))
  1712.     goto err2;
  1713. #endif
  1714.  
  1715.     convert_byteorder(timestamp,4); /* convert timestamp from external form */
  1716.     memcpy (xtimestamp, timestamp, 4);    /* Return signature timestamp */
  1717.  
  1718.     burn(inbuf);    /* burn sensitive data on stack */
  1719.     burn(outbuf);    /* burn sensitive data on stack */
  1720.     return(0);    /* normal return */
  1721.  
  1722. err1:
  1723.     burn(inbuf);    /* burn sensitive data on stack */
  1724.     burn(outbuf);    /* burn sensitive data on stack */
  1725.     return(-1);    /* error return */
  1726.  
  1727. badcert2:    /* Bad packet.  Complain. */
  1728.     fprintf(pgpout,PSTR("\n\007Error: Badly-formed or corrupted signature certificate.\n"));
  1729.     /* Now just drop through to error exit... */
  1730.  
  1731. err2:
  1732.     burn(inbuf);    /* burn sensitive data on stack */
  1733.     burn(outbuf);    /* burn sensitive data on stack */
  1734.     return(-2);    /* error return */
  1735.  
  1736. }    /* check_key_sig */
  1737.  
  1738.  
  1739.  
  1740. /*======================================================================*/
  1741. int squish_and_idea_file(byte *ideakey, FILE *f, FILE *g, 
  1742.     boolean attempt_compression)
  1743. {
  1744.     FILE *t;
  1745.     byte ctb;
  1746.     word32 fpos, fpos0;
  1747.     extern char plainfile[];
  1748.  
  1749.     /*
  1750.     **  If the caller specified that we should attempt compression, we
  1751.     **  create a temporary file 't' and compress our input file 'f' into
  1752.     **  't'.  Ideally, we would see if we get a good compression ratio 
  1753.     **  and if we did, then use file 't' for input and write a 
  1754.     **  CTB_COMPRESSED prefix.  But in this implementation we just always
  1755.     **  use the compressed output, even if it didn't compress well.
  1756.     */
  1757.  
  1758.     rewind( f );
  1759.  
  1760.     if (!attempt_compression)
  1761.         t = f;    /* skip compression attempt */
  1762.     else    /* attempt compression-- get a tempfile */ 
  1763.         if ((t = tmpfile()) == NULL) /* error: no tempfile */
  1764.             t = f;    /* skip compression attempt */
  1765.         else    /* attempt compression */ 
  1766.         {
  1767.             extern int zipup( FILE *, FILE * );
  1768.  
  1769.             if (verbose) fprintf(pgpout, PSTR("\nCompressing plaintext [%s]..."),
  1770.                 plainfile );
  1771.  
  1772.             /* We don't put a length field on CTB_COMPRESSED yet */
  1773.             ctb = CTB_COMPRESSED;        /* use compression prefix CTB */
  1774.             fwrite( &ctb, 1, 1, t );    /* write CTB_COMPRESSED */
  1775.               /* No CTB packet length specified means indefinite length. */
  1776.             ctb = ZIP2_ALGORITHM_BYTE;     /* use ZIP compression */
  1777.             fwrite( &ctb, 1, 1, t );    /* write ZIP algorithm byte */
  1778.  
  1779.             /* Compression the file */
  1780.             zipup( f, t);
  1781.             if (verbose) fprintf(pgpout, PSTR("compressed.  ") );
  1782.             else fputc('.',pgpout);    /* show progress */
  1783.             rewind( t );
  1784.           }
  1785.  
  1786.     /*    Now write out file thru IDEA cipher... */
  1787.  
  1788.     /* Write CTB prefix, leave 4 bytes for later length */
  1789.     fpos0 = ftell(g);
  1790.     write_ctb_len (g, CTB_CKE_TYPE, 0L, TRUE);
  1791.     fpos = ftell(g) - fpos0;
  1792.  
  1793.     idea_file( ideakey, ENCRYPT_IT, t, g, fsize(t) );
  1794.  
  1795.     /* Now re-write CTB prefix, this time with length */
  1796.     fseek(g,fpos0,SEEK_SET);
  1797.     write_ctb_len (g, CTB_CKE_TYPE, fsize(g)-fpos, TRUE);
  1798.  
  1799.     if (t != f)    
  1800.     {    wipeout( t );
  1801.         fclose( t );  /* close and remove the temporary file */
  1802.     }
  1803.  
  1804.     return(0);    /* normal return */
  1805.  
  1806. }    /* squish_and_idea_file */
  1807.  
  1808.  
  1809. int squish_file(char *infile, char *outfile)
  1810. {
  1811.     FILE *f, *g;
  1812.     byte ctb;
  1813.     extern int zip( FILE *, FILE * );
  1814.  
  1815.     if (verbose)
  1816.         fprintf(pgpout,PSTR("\nInput file: %s, compressed file: %s\n"),
  1817.         infile,outfile);
  1818.  
  1819.     /* open file f for read, in binary (not text) mode...*/
  1820. #ifdef VMS
  1821.     if ((f = fopen( infile, "rb", "ctx=stm" )) == NULL)
  1822. #else
  1823.     if ((f = fopen( infile, "rb" )) == NULL)
  1824. #endif
  1825.     {
  1826.         fprintf(pgpout,PSTR("\n\007Can't open file '%s'\n"), infile );
  1827.         return(-1);
  1828.     }
  1829.  
  1830.     /* open file g for write, in binary (not text) mode...*/
  1831.     if ((g = fopen( outfile, "wb" )) == NULL)
  1832.     {
  1833.         fprintf(pgpout,PSTR("\n\007Can't create compressed file '%s'\n"), outfile );
  1834.         fclose(f);
  1835.         return(-1);
  1836.     }
  1837.  
  1838.  
  1839.     if (verbose) fprintf(pgpout, PSTR("Compressing file..."));
  1840.  
  1841.     /* We don't put a length field on CTB_COMPRESSED yet */
  1842.     ctb = CTB_COMPRESSED;        /* use compression prefix CTB */
  1843.     fwrite( &ctb, 1, 1, g );    /* write CTB_COMPRESSED */
  1844.     /* No CTB packet length specified means indefinite length. */
  1845.     ctb = ZIP2_ALGORITHM_BYTE;     /* use ZIP compression */
  1846.     fwrite( &ctb, 1, 1, g );    /* write ZIP algorithm byte */
  1847.  
  1848.     /* Compress/store the file */
  1849.     zipup( f, g );
  1850.     if (verbose) fprintf(pgpout, PSTR("compressed.  ") );
  1851.  
  1852.     fclose (f);
  1853.     fclose (g);
  1854.     return(0);
  1855. }   /* squish_file */
  1856.  
  1857. #define NOECHO1 1    /* Disable password from being displayed on screen */
  1858. #define NOECHO2 2    /* Disable password from being displayed on screen */
  1859.  
  1860. int idea_encryptfile(char *infile, char *outfile, 
  1861.     boolean attempt_compression)
  1862. {
  1863.     FILE *f;    /* input file */
  1864.     FILE *g;    /* output file */
  1865.     byte ideakey[16];
  1866.     byte passphrase[256];
  1867.  
  1868.     if (verbose)
  1869.         fprintf(pgpout,PSTR("\nPlaintext file: %s, ciphertext file: %s\n"),
  1870.         infile,outfile);
  1871.  
  1872.     /* open file f for read, in binary (not text) mode...*/
  1873. #ifdef VMS
  1874.     if ((f = fopen( infile, "rb", "ctx=stm" )) == NULL)
  1875. #else
  1876.     if ((f = fopen( infile, "rb" )) == NULL)
  1877. #endif
  1878.     {
  1879.         fprintf(pgpout,PSTR("\n\007Can't open plaintext file '%s'\n"), infile );
  1880.         return(-1);
  1881.     }
  1882.  
  1883.     /* open file g for write, in binary (not text) mode...*/
  1884.     if ((g = fopen( outfile, "wb" )) == NULL)
  1885.     {
  1886.         fprintf(pgpout,PSTR("\n\007Can't create ciphertext file '%s'\n"), outfile );
  1887.         fclose(f);
  1888.         return(-1);
  1889.     }
  1890.  
  1891.     /* Get IDEA password, hashed to a key */
  1892.     fprintf(pgpout,PSTR("\nYou need a pass phrase to encrypt the file. "));
  1893.     if (getideakey((char *)passphrase,(char *)ideakey,NOECHO2) <= 0)
  1894.     {    fclose(f);
  1895.         fclose(g);
  1896.         return(-1);
  1897.     }
  1898.  
  1899.     fprintf(pgpout,PSTR("Just a moment..."));  /* this may take a while */
  1900.     fflush(pgpout);
  1901.  
  1902.     /* Now compress the plaintext and encrypt it with IDEA... */
  1903.     squish_and_idea_file( ideakey, f, g, attempt_compression );
  1904.  
  1905.     burn(ideakey);    /* burn sensitive data on stack */
  1906.     burn(passphrase);
  1907.  
  1908.     fclose(g);
  1909.     fclose(f);
  1910.  
  1911.     return(0);
  1912.  
  1913. }    /* idea_encryptfile */
  1914.  
  1915.  
  1916. /*======================================================================*/
  1917.  
  1918.  
  1919. int encryptfile(char *mcguffin, char *infile, char *outfile, 
  1920.     boolean attempt_compression)
  1921. {
  1922.     byte randompad[MAX_BYTE_PRECISION];    /* buffer of random pad bytes */
  1923.     int i,blocksize,ckp_length;
  1924.     FILE *f;
  1925.     FILE *g;
  1926.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
  1927.     byte inbuf[MAX_BYTE_PRECISION];
  1928.     byte outbuf[MAX_BYTE_PRECISION];
  1929.     word32 tstamp; byte *timestamp = (byte *) &tstamp;        /* key certificate timestamp */
  1930.     byte userid[256];
  1931.     byte ideakey[16]; /* must be big enough for make_random_ideakey */
  1932.     char keyfile[MAX_PATH];    /* for getpublickey */
  1933.     long fp;    /* unused, just to satisfy getpublickey */
  1934.     int pktlen;    /* unused, just to satisfy getpublickey */
  1935.     word32 chksum;
  1936.     byte    ver, alg;
  1937.  
  1938.  
  1939.     buildfilename(keyfile,PUBLIC_KEYRING_FILENAME); /* use default pathname */
  1940.  
  1941.     if (verbose)
  1942.         fprintf(pgpout,PSTR("\nPlaintext file: %s, ciphertext file: %s\n"),
  1943.         infile,outfile);
  1944.  
  1945.     userid[0] = '\0';
  1946.     if (mcguffin)
  1947.         strcpy((char *)userid,mcguffin);/* Who we are looking for (C string) */
  1948.  
  1949.     /*    Get and validate public key from a key file: */
  1950.     if (getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen, NULL, timestamp, userid, n, e) < 0)
  1951.     {    return(-1);
  1952.     }
  1953.  
  1954.     if (warn_signatures(keyfile, fp, pktlen, (char *)userid, FALSE) < 0)
  1955.         return(-1);
  1956.  
  1957.     /* set_precision has been properly called by getpublickey */
  1958.  
  1959.     /*    Note that RSA key must be at least big enough to encipher a 
  1960.         complete conventional key packet in a single RSA block.
  1961.     */
  1962.  
  1963.     blocksize = countbytes(n)-1;    /* size of a plaintext block */
  1964.     if (blocksize < 31)
  1965.     {    fprintf(pgpout,"\n\007Error: RSA key length must be at least 256 bits.\n");
  1966.         return(-1);
  1967.     }
  1968.  
  1969.     /* open file f for read, in binary (not text) mode...*/
  1970. #ifdef VMS
  1971.     if ((f = fopen( infile, "rb", "ctx=stm" )) == NULL)
  1972. #else
  1973.     if ((f = fopen( infile, "rb" )) == NULL)
  1974. #endif
  1975.     {
  1976.         fprintf(pgpout,PSTR("\n\007Can't open plaintext file '%s'\n"), infile );
  1977.         return(-1);
  1978.     }
  1979.  
  1980.     /* open file g for write, in binary (not text) mode...*/
  1981.     if ((g = fopen( outfile, "wb" )) == NULL)
  1982.     {
  1983.         fprintf(pgpout,PSTR("\n\007Can't create ciphertext file '%s'\n"), outfile );
  1984.         fclose(f);
  1985.         return(-1);
  1986.     }
  1987.  
  1988.     /*    Now we have to time some user keystrokes to get some random
  1989.         bytes for generating a random IDEA cipher key.
  1990.         We would have to solicit fewer keystrokes for random IDEA
  1991.         key generation if we had already accumulated some keystrokes
  1992.         incidental to some other purpose, such as asking for a password 
  1993.         to decode an RSA secret key so that a signature could be applied 
  1994.         to the message before encrypting it.
  1995.     */
  1996.  
  1997.     ckp_length = make_random_ideakey(ideakey);
  1998.     /* Returns an 16 byte random IDEA key */
  1999.  
  2000. #ifdef XLOWFIRST    /* Assumes LSB-first order */
  2001.     for (i=0; i<ckp_length; ++i)
  2002.         outbuf[i] = ideakey[i];
  2003.     /* Compute and append checksum to the key */
  2004.     chksum = checksum (outbuf, ckp_length);
  2005.     put_word16((word16) chksum, outbuf+ckp_length);
  2006.     ckp_length += 2;
  2007.     /* Append identifier byte to key */
  2008.     outbuf[ckp_length++] = IDEA_ALGORITHM_BYTE;
  2009. #else    /* Assumes MSB-first order */
  2010.     /* Prepend identifier byte to key */
  2011.     outbuf[0] = IDEA_ALGORITHM_BYTE;
  2012.     for (i=0; i<ckp_length; ++i)
  2013.         outbuf[i+1] = ideakey[i];
  2014.     /* Compute and append checksum to the key */
  2015.     chksum = checksum (outbuf+1, ckp_length);
  2016.     ckp_length++;
  2017.     put_word16((word16) chksum, outbuf+ckp_length);
  2018.     ckp_length += 2;
  2019. #endif
  2020.  
  2021.     /*
  2022.     **    Messages encrypted with a public key should use random padding, 
  2023.     **    while messages "signed" with a secret key should use constant 
  2024.     **    padding.
  2025.     */
  2026.  
  2027.     for (i = 0; i < (blocksize - ckp_length); i++)
  2028.         while (!(randompad[i] = randombyte()))
  2029.             ;    /* Allow only nonzero values */
  2030.  
  2031.     /*
  2032.     **    Note that RSA key must be at least big enough to encipher a
  2033.     **    complete conventional key packet in a single RSA block.
  2034.     */
  2035.  
  2036.     /* ckp_length is conventional key packet length. */
  2037.  
  2038.     preblock( (unitptr)inbuf, outbuf, ckp_length, n, randompad );
  2039.     mp_modexp( (unitptr)outbuf, (unitptr)inbuf, e, n );    /* RSA encrypt */
  2040.  
  2041.     /* write out header record to outfile ... */
  2042.  
  2043.     /* PKE is Public Key Encryption */
  2044.     write_ctb_len (g, CTB_PKE_TYPE,
  2045.          1+KEYFRAGSIZE+1+2+countbytes((unitptr)outbuf), FALSE);
  2046.  
  2047.     /* Write version byte */
  2048.     ver = VERSION_BYTE;
  2049.     fwrite (&ver, 1, 1, g);
  2050.  
  2051.     writekeyID( n, g );    /* write msg prefix fragment of modulus n */
  2052.  
  2053.     /* Write algorithm byte */
  2054.     alg = RSA_ALGORITHM_BYTE;
  2055.     fwrite (&alg, 1, 1, g);
  2056.  
  2057.     /* convert RSA ciphertext block via reg2mpi and write to file */
  2058.  
  2059.     write_mpi( (unitptr)outbuf, g, FALSE );
  2060.  
  2061.     burn(inbuf);    /* burn sensitive data on stack */
  2062.     burn(outbuf);    /* burn sensitive data on stack */
  2063.  
  2064.     /**    Finished with RSA block containing IDEA key. */
  2065.  
  2066.     /* Now compress the plaintext and encrypt it with IDEA... */
  2067.     squish_and_idea_file( ideakey, f, g, attempt_compression );
  2068.  
  2069.     burn(ideakey);    /* burn sensitive data on stack */
  2070.  
  2071.     fclose(g);
  2072.     fclose(f);
  2073.  
  2074.     return(0);
  2075. }    /* encryptfile */
  2076.  
  2077.  
  2078. /*======================================================================*/
  2079. int make_literal(char *infile, char *outfile, char lit_mode, char *literalfile)
  2080. {    /*    Prepend a CTB_LITERAL prefix to a file.  Convert to canonical form if
  2081.         lit_mode is MODE_TEXT.
  2082.     */
  2083.     char lfile[MAX_PATH];
  2084.     FILE *f;
  2085.     FILE *g;
  2086.     word32 flen, fpos;
  2087.     word32 dummystamp = 0;
  2088.  
  2089.     if (verbose)
  2090.         fprintf(pgpout,PSTR("\nInput plaintext file: %s, Output plaintext file: %s\n"),
  2091.         infile,outfile);
  2092.  
  2093.     /* open file f for read, in binary or text mode...*/
  2094. #ifdef CANONICAL_TEXT
  2095.     if ((f = fopen(infile,"rb")) == NULL)    /* Always binary */
  2096. #else
  2097.     if ((f = fopen(infile,(lit_mode==MODE_BINARY)?"rb":"r")) == NULL)
  2098. #endif
  2099.     {    fprintf(pgpout,PSTR("\n\007Can't open input plaintext file '%s'\n"),infile);
  2100.         return(-1);
  2101.     }
  2102.     flen = fsize(f);
  2103.  
  2104.     /*     open file g for write, in binary (not text) mode... */
  2105.     if ((g = fopen( outfile,"wb" )) == NULL)
  2106.     {    fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
  2107.         goto err1;
  2108.     }
  2109.  
  2110.     if (lit_mode == MODE_BINARY)
  2111.         write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
  2112.     else
  2113. #ifdef CANONICAL_TEXT
  2114.         write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
  2115. #else
  2116.         /* Will put in size field later for text mode */
  2117.         write_ctb_len (g, CTB_LITERAL_TYPE, 0L, TRUE);
  2118. #endif
  2119.     fwrite ( &lit_mode, 1, 1, g );    /*    write lit_mode */
  2120.     /* write literalfile name */
  2121.     if (literalfile == NULL)
  2122.     {    /* Put in a zero byte to indicate no filename */
  2123.         fputc ('\0', g);
  2124.     }
  2125.     else
  2126.     {    strcpy( lfile, literalfile );
  2127.         file_to_canon( lfile );
  2128.         CToPascal( lfile );
  2129.         fwrite ( lfile, 1, lfile[0]+1, g);
  2130.     } 
  2131.     /* Dummy file creation timestamp */
  2132.     fwrite ( &dummystamp, 1, sizeof(dummystamp), g);
  2133.  
  2134.     fpos = ftell(g);
  2135.  
  2136.     CONVERSION = (lit_mode == MODE_TEXT) ? INT_CONV : NO_CONV;
  2137. #ifdef CANONICAL_TEXT
  2138.     copyfile( f, g, -1L );    /* Simple copy on canonical systems */
  2139.     CONVERSION = NO_CONV;
  2140. #else
  2141.     if (lit_mode == MODE_BINARY)
  2142.         copyfile( f, g, -1L );
  2143.     else
  2144.     {    copyfile_to_canon( f, g, -1L );
  2145.         CONVERSION = NO_CONV;
  2146.         /* Re-write CTB with correct length info */
  2147.         rewind (g);
  2148.         write_ctb_len (g, CTB_LITERAL_TYPE, fsize(f)-fpos, TRUE);
  2149.     }
  2150. #endif
  2151.             
  2152.     fclose(g);
  2153.     fclose(f);
  2154.     return(0);    /* normal return */
  2155.  
  2156. err1:
  2157.     fclose(f);
  2158.     return(-1);    /* error return */
  2159.  
  2160. }    /* make_literal */
  2161.  
  2162.  
  2163. /*======================================================================*/
  2164. int strip_literal(char *infile, char *outfile, boolean explicit_outfile_flag,
  2165.         char *lit_mode)
  2166. {    /*    Strip off literal prefix from infile, copying to outfile.
  2167.         Get lit_mode and literalfile info from
  2168.         the prefix.  Replace outfile with literalfile unless
  2169.         literalfile is illegal or explicit_outfile_flag is TRUE.
  2170.         If lit_mode is MODE_TEXT, convert from canonical form as we
  2171.         copy the data.
  2172.     */
  2173.     byte ctb;    /* Cipher Type Byte */
  2174.     FILE *f;
  2175.     FILE *g;
  2176.     word32 LITlength = 0;
  2177.     unsigned char litfile[MAX_PATH];
  2178.     word32 dummystamp;
  2179.  
  2180.     *lit_mode = MODE_BINARY;
  2181.     if (verbose)
  2182.         fprintf(pgpout,PSTR("\nInput plaintext file: %s, Output plaintext file: %s\n"),
  2183.         infile,outfile);
  2184.  
  2185.     /* open file f for read, in binary (not text) mode...*/
  2186. #ifdef VMS
  2187.     if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
  2188. #else
  2189.     if ((f = fopen(infile,"rb")) == NULL)
  2190. #endif
  2191.     {    fprintf(pgpout,PSTR("\n\007Can't open input plaintext file '%s'\n"),infile);
  2192.         return(-1);
  2193.     }
  2194.  
  2195.     fread(&ctb,1,1,f);    /* read Cipher Type Byte */
  2196.  
  2197.     if (!is_ctb(ctb) || !(is_ctb_type(ctb,CTB_LITERAL_TYPE))) 
  2198.     {    /* debug message in English only -- something got corrupted */
  2199.         fprintf(pgpout,"\n\007'%s' is not a literal plaintext file.\n",infile);
  2200.         fclose(f);
  2201.         return(-1);
  2202.     }
  2203.  
  2204.     LITlength = getpastlength(ctb, f); /* read packet length */
  2205.  
  2206.     /* Read literal data */
  2207.     *lit_mode = '\0';
  2208.     fread (lit_mode,1,1,f);
  2209.     if ((*lit_mode != MODE_BINARY) && (*lit_mode != MODE_TEXT))
  2210.     {    (void) version_error(*lit_mode, MODE_TEXT);
  2211.         fclose(f);
  2212.         return(-1);
  2213.     }
  2214.     if (verbose)
  2215.         fprintf(pgpout, PSTR("File type: '%c'\n"), lit_mode);
  2216.     /* Read literal file name, use it if possible */
  2217.     litfile[0] = 0;
  2218.     fread (litfile,1,1,f);
  2219.     if ((int)litfile[0] > MAX_PATH)
  2220.         litfile[0] = 0;    /* If too long for us, ignore it */
  2221.     if (litfile[0] > 0)
  2222.         fread (litfile+1,1,litfile[0],f);
  2223.     /* Use litfile if it's writeable and he didn't say an outfile */
  2224.     if (litfile[0] > 0)
  2225.     {    PascalToC( (char *)litfile );
  2226.         if (verbose)
  2227.             fprintf(pgpout, PSTR("Original plaintext file name was: '%s'\n"), litfile);
  2228.         if (!strcmp((char *) litfile, CONSOLE_FILENAME) || !explicit_outfile_flag)
  2229.         {    file_from_canon( (char *)litfile );
  2230.             if (file_ok_write( (char *)litfile ))
  2231.                 strcpy ( outfile, (char *)litfile );
  2232.         }
  2233.     }
  2234.     /* Discard file creation timestamp for now */
  2235.     fread (&dummystamp, 1, sizeof(dummystamp), f);
  2236.  
  2237.     if (file_exists( outfile ))
  2238.     {    fprintf(pgpout, PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "), outfile );
  2239.         if (! getyesno( 'n' ))
  2240.             goto err1;        /* user said don't do it - abort operation */
  2241.     }
  2242.  
  2243.     /*     open file g for write, in binary or text mode... */
  2244. #ifdef CANONICAL_TEXT
  2245.     if ((g = fopen( outfile, "wb" )) == NULL) /* Always binary */
  2246. #else
  2247.     if ((g = fopen( outfile, (*lit_mode==MODE_BINARY)?"wb":"w" )) == NULL)
  2248. #endif
  2249.     {    fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
  2250.         goto err1;
  2251.     }
  2252.  
  2253.     /* copy rest of literal plaintext file */
  2254.     CONVERSION = (*lit_mode == MODE_TEXT) ? EXT_CONV : NO_CONV;
  2255. #ifdef CANONICAL_TEXT
  2256.     copyfile( f, g, LITlength );    /* Simple copy on canonical systems */
  2257. #else
  2258.     if (*lit_mode == MODE_BINARY)
  2259.         copyfile( f, g, LITlength );
  2260.     else
  2261.         copyfile_from_canon( f, g, LITlength );
  2262. #endif
  2263.     CONVERSION = NO_CONV;
  2264.  
  2265.     fclose(g);
  2266.     fclose(f);
  2267.     return(0);    /* normal return */
  2268.  
  2269. err1:
  2270.     fclose(f);
  2271.     return(-1);    /* error return */
  2272.  
  2273. }    /* strip_literal */
  2274.  
  2275.  
  2276. /*======================================================================*/
  2277.  
  2278.  
  2279. int decryptfile(char *infile, char *outfile)
  2280. {
  2281.     byte ctb;    /* Cipher Type Byte */
  2282.     byte ctbCKE; /* Cipher Type Byte */
  2283.     FILE *f;
  2284.     FILE *g;
  2285.     int count, status;
  2286.     unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION];
  2287.     unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
  2288.     byte inbuf[MAX_BYTE_PRECISION];
  2289.     byte outbuf[MAX_BYTE_PRECISION];
  2290.     byte keyID[KEYFRAGSIZE];
  2291.     word32 tstamp; byte *timestamp = (byte *) &tstamp;        /* key certificate timestamp */
  2292.     byte userid[256];
  2293.     word32 flen;
  2294.     byte ver, alg;
  2295.     word16 chksum;
  2296.  
  2297.     set_precision(MAX_UNIT_PRECISION);    /* safest opening assumption */
  2298.  
  2299.     if (verbose)
  2300.         fprintf(pgpout,PSTR("\nCiphertext file: %s, plaintext file: %s\n"),
  2301.         infile,outfile);
  2302.  
  2303.     /* open file f for read, in binary (not text) mode...*/
  2304. #ifdef VMS
  2305.     if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
  2306. #else
  2307.     if ((f = fopen(infile,"rb")) == NULL)
  2308. #endif
  2309.     {    fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),infile);
  2310.         return(-1);
  2311.     }
  2312.  
  2313.     fread(&ctb,1,1,f);    /* read Cipher Type Byte */
  2314.     if (!is_ctb(ctb))
  2315.     {    fprintf(pgpout,PSTR("\n\007'%s' is not a cipher file.\n"),infile);
  2316.         fclose(f);
  2317.         return(-1);
  2318.     }
  2319.  
  2320.     /* PKE is Public Key Encryption */
  2321.     if (!is_ctb_type(ctb,CTB_PKE_TYPE))
  2322.     {    fprintf(pgpout,PSTR("\n\007'%s' is not enciphered with a public key.\n"),infile);
  2323.         fclose(f);
  2324.         return(-1);
  2325.     }
  2326.  
  2327.     getpastlength(ctb, f); /* read packet length */
  2328.  
  2329.     /* Read and check version */
  2330.     fread (&ver, 1, 1, f);
  2331.     if (version_error(ver, VERSION_BYTE))
  2332.     {    fclose (f);
  2333.         return (-1);
  2334.     }
  2335.  
  2336.     fread(keyID,1,KEYFRAGSIZE,f); /* read key ID */
  2337.     /* Use keyID prefix to look up key. */
  2338.  
  2339.     /* Read and check algorithm */
  2340.     fread (&alg, 1, 1, f);
  2341.     if (version_error(alg, RSA_ALGORITHM_BYTE))
  2342.     {    fclose (f);
  2343.         return (-1);
  2344.     }
  2345.  
  2346.     /*    Get and validate secret key from a key file: */
  2347.     if (getsecretkey(FALSE, TRUE, NULL, keyID, timestamp, NULL, NULL,userid,
  2348.                          n, e, d, p, q, u) < 0)
  2349.     {    fclose(f);
  2350.         return(-1);
  2351.     }
  2352.  
  2353.     /*    Note that RSA key must be at least big enough to encipher a
  2354.         complete conventional key packet in a single RSA block. */
  2355.  
  2356.     /*==================================================================*/
  2357.     /* read ciphertext block, converting to internal format: */
  2358.     read_mpi((unitptr)inbuf, f, FALSE, FALSE);
  2359.  
  2360.     fprintf(pgpout,PSTR("Just a moment..."));    /* RSA will take a while. */
  2361.     fflush(pgpout);
  2362.  
  2363.     rsa_decrypt((unitptr)outbuf, (unitptr)inbuf, d, p, q, u);
  2364.  
  2365.     fputc('.',pgpout);    /* Signal RSA completion. */
  2366.  
  2367.     if ((count = postunblock(outbuf, (unitptr)outbuf, n)) < 0)
  2368.     {    fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
  2369. This may be caused either by corrupted data or by using the wrong RSA key.\n"));
  2370.         fclose(f);
  2371.         return(-1);
  2372.     }
  2373.  
  2374.     /* Verify that top of buffer has correct algorithm byte */
  2375.     --count;    /* one less byte to drop algorithm byte */
  2376. #ifdef XLOWFIRST    /* Assumes LSB-first order */
  2377.     if (version_error(outbuf[count], IDEA_ALGORITHM_BYTE))
  2378. #else        /* Assumes MSB-first order */
  2379.     if (version_error(outbuf[0], IDEA_ALGORITHM_BYTE))
  2380. #endif
  2381.     {    fclose(f);
  2382.         return(-1);
  2383.     }
  2384.  
  2385.     /* Verify checksum */
  2386.     count -= 2;    /* back up before checksum */
  2387. #ifdef XLOWFIRST    /* Assumes LSB-first order */
  2388.     chksum = fetch_word16(outbuf+count);
  2389.     if (chksum != checksum(outbuf, count))
  2390. #else        /* Assumes MSB-first order */
  2391.     chksum = fetch_word16(outbuf+1+count);
  2392.     if (chksum != checksum(outbuf+1, count))
  2393. #endif
  2394.     {    fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
  2395. This may be caused either by corrupted data or by using the wrong RSA key.\n"));
  2396.         fclose(f);
  2397.         return(-1);
  2398.     }
  2399.  
  2400.     /* outbuf should contain random IDEA key packet */
  2401.     /*==================================================================*/
  2402.  
  2403.     if (file_exists( outfile ))
  2404.     {    fprintf(pgpout, PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "), outfile );
  2405.         if (! getyesno( 'n' ))
  2406.             goto err1;        /* user said don't do it - abort operation */
  2407.     }
  2408.  
  2409.     /*     open file g for write, in binary (not text) mode... */
  2410.     if ((g = fopen( outfile, "wb" )) == NULL)
  2411.     {    fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
  2412.         goto err1;
  2413.     }
  2414.  
  2415.     fread(&ctbCKE,1,1,f);    /* read Cipher Type Byte, should be CTB_CKE */
  2416.     if (!is_ctb(ctbCKE) || !is_ctb_type(ctbCKE,CTB_CKE_TYPE))
  2417.     {    /* Should never get here. */
  2418.         fprintf(pgpout,"\007\nBad or missing CTB_CKE byte.\n");
  2419.         goto err1;    /* Abandon ship! */
  2420.     }
  2421.  
  2422.     flen = getpastlength(ctbCKE, f); /* read packet length */
  2423.  
  2424.     /* Decrypt ciphertext file */
  2425. #ifdef XLOWFIRST    /* Assumes LSB-first order */
  2426.     status = idea_file( outbuf, DECRYPT_IT, f, g, flen );
  2427. #else        /* Assumes MSB-first order */
  2428.     status = idea_file( outbuf+1, DECRYPT_IT, f, g, flen );
  2429. #endif
  2430.     if (status < 0)
  2431.     {    fprintf(pgpout,PSTR("\n\007Error: Decrypted plaintext is corrupted.\n"));
  2432.     }
  2433.     fputc('.',pgpout);    /* show progress */
  2434.  
  2435.     fclose(g);
  2436.     fclose(f);
  2437.     burn(inbuf);    /* burn sensitive data on stack */
  2438.     burn(outbuf);    /* burn sensitive data on stack */
  2439.     mp_burn(d);    /* burn sensitive data on stack */
  2440.     mp_burn(p);    /* burn sensitive data on stack */
  2441.     mp_burn(q);    /* burn sensitive data on stack */
  2442.     mp_burn(u);    /* burn sensitive data on stack */
  2443.     if (status < 0)    /* if idea_file failed, then error return */
  2444.         return(status);
  2445.     return(1);    /* always indicate output file has nested stuff in it. */
  2446.  
  2447. err1:
  2448.     fclose(f);
  2449.     burn(inbuf);    /* burn sensitive data on stack */
  2450.     burn(outbuf);    /* burn sensitive data on stack */
  2451.     mp_burn(d);    /* burn sensitive data on stack */
  2452.     mp_burn(p);    /* burn sensitive data on stack */
  2453.     mp_burn(q);    /* burn sensitive data on stack */
  2454.     mp_burn(u);    /* burn sensitive data on stack */
  2455.     return(-1);    /* error return */
  2456.  
  2457. }    /* decryptfile */
  2458.  
  2459.  
  2460.  
  2461. int idea_decryptfile(char *infile, char *outfile)
  2462. {
  2463.     byte ctb;    /* Cipher Type Byte */
  2464.     FILE *f;
  2465.     FILE *g;
  2466.     byte ideakey[16];
  2467.     byte passphrase[256];
  2468.     int status;
  2469.     word32 flen;
  2470.  
  2471.     if (verbose)
  2472.         fprintf(pgpout,PSTR("\nCiphertext file: %s, plaintext file: %s\n"),
  2473.         infile,outfile);
  2474.  
  2475.     /* open file f for read, in binary (not text) mode...*/
  2476. #ifdef VMS
  2477.     if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
  2478. #else
  2479.     if ((f = fopen(infile,"rb")) == NULL)
  2480. #endif
  2481.     {    fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),infile);
  2482.         return(-1);
  2483.     }
  2484.  
  2485.     fread(&ctb,1,1,f);    /* read Cipher Type Byte, should be CTB_CKE */
  2486.  
  2487.     if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_CKE_TYPE))
  2488.     {    /* Should never get here. */
  2489.         fprintf(pgpout,"\007\nBad or missing CTB_CKE byte.\n");
  2490.         goto err1;    /* Abandon ship! */
  2491.     }
  2492.  
  2493.     flen = getpastlength(ctb, f); /* read packet length */
  2494.  
  2495.     if (file_exists( outfile ))
  2496.     {    fprintf(pgpout, PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "), outfile );
  2497.         if (! getyesno( 'n' ))
  2498.             goto err1;        /* user said don't do it - abort operation */
  2499.     }
  2500.  
  2501.     /*     open file g for write, in binary (not text) mode... */
  2502.     if ((g = fopen( outfile, "wb" )) == NULL)
  2503.     {    fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
  2504.         goto err1;
  2505.     }
  2506.  
  2507.     /* Get IDEA password, hashed */
  2508.     fprintf(pgpout,PSTR("\nYou need a pass phrase to decrypt this file. "));
  2509.     if (getideakey((char *)passphrase,(char *)ideakey,NOECHO1) <= 0)
  2510.     {    fclose(f);
  2511.         fclose(g);
  2512.         return(-1);
  2513.     }
  2514.  
  2515.     fprintf(pgpout,PSTR("Just a moment..."));  /* this may take a while */
  2516.     fflush(pgpout);
  2517.  
  2518.     status = idea_file( ideakey, DECRYPT_IT, f, g, flen );
  2519.  
  2520.     burn(ideakey);    /* burn sensitive data on stack */
  2521.     burn(passphrase);
  2522.  
  2523.     fputc('.',pgpout);    /* show progress */
  2524.  
  2525.     fclose(g);
  2526.     fclose(f);
  2527.  
  2528.     if (status < 0)    /* if idea_file failed, then complain */
  2529.     {    fprintf(pgpout,PSTR("\n\007Error:  Bad pass phrase.\n"));
  2530.         remove(outfile);    /* throw away our mistake */
  2531.         return(status);        /* error return */
  2532.     }
  2533.     fprintf(pgpout,PSTR("Pass phrase appears good. "));
  2534.     return(1);    /* always indicate output file has nested stuff in it. */
  2535.  
  2536. err1:
  2537.     fclose(f);
  2538.     return(-1);    /* error return */
  2539.  
  2540. }    /* idea_decryptfile */
  2541.  
  2542.  
  2543.  
  2544. int decompress_file(char *infile, char *outfile)
  2545. {
  2546.     byte ctb;
  2547.     FILE *f;
  2548.     FILE *g;
  2549.     extern void lzhDecode( FILE *, FILE * );
  2550.     extern void unzip( FILE *, FILE * );
  2551.     if (verbose) fprintf(pgpout, PSTR("Decompressing plaintext...") );
  2552.  
  2553.     /* open file f for read, in binary (not text) mode...*/
  2554. #ifdef VMS
  2555.     if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
  2556. #else
  2557.     if ((f = fopen(infile,"rb")) == NULL)
  2558. #endif
  2559.     {    fprintf(pgpout,PSTR("\n\007Can't open compressed file '%s'\n"),infile);
  2560.         return(-1);
  2561.     }
  2562.  
  2563.     fread(&ctb,1,1,f);    /* read and skip over Cipher Type Byte */
  2564.     if (!is_ctb_type( ctb, CTB_COMPRESSED_TYPE ))
  2565.     {    /* Shouldn't get here, or why were we called to begin with? */
  2566.         fprintf(pgpout,"\007\nBad or missing CTB_COMPRESSED byte.\n");
  2567.         goto err1;    /* Abandon ship! */
  2568.     }
  2569.  
  2570.     getpastlength(ctb, f); /* read packet length */
  2571.     /* The packet length is ignored.  Assume it's huge. */
  2572.  
  2573.     fread(&ctb,1,1,f);    /* read and skip over compression algorithm byte */
  2574.     if (ctb != ZIP2_ALGORITHM_BYTE)
  2575.     {    /* We only know how to uncompress deflate-compressed data.  We
  2576.            may hit imploded or Lharc'ed data but treat it as an error just
  2577.            the same */
  2578.         fprintf(pgpout,PSTR("\007\nUnrecognized compression algorithm.\n\
  2579. This may require a newer version of PGP.\n"));
  2580.         goto err1;    /* Abandon ship! */
  2581.     }
  2582.  
  2583.     /*     open file g for write, in binary (not text) mode... */
  2584.     if ((g = fopen( outfile, "wb" )) == NULL)
  2585.     {    fprintf(pgpout, PSTR("\n\007Can't create decompressed file '%s'\n"), outfile );
  2586.         goto err1;
  2587.     }
  2588.  
  2589.     unzip( f, g );
  2590.     if (verbose) fprintf(pgpout, PSTR("done.  ") );
  2591.     else fputc('.',pgpout);    /* show progress */
  2592.  
  2593.     fclose(g);
  2594.     fclose(f);
  2595.     return(1);    /* always indicate output file has nested stuff in it. */
  2596. err1:
  2597.     fclose(f);
  2598.     return(-1);    /* error return */
  2599.  
  2600. }    /* decompress_file */
  2601.  
  2602.